From f5f8c19f6c7bd70d82de0c6e07135524a725428e Mon Sep 17 00:00:00 2001 From: Quentin Perret Date: Wed, 31 May 2023 16:44:36 +0000 Subject: [PATCH] ANDROID: KVM: arm64: Allow state changes of MMIO pages We've historically disallowed state changes for MMIO pages -- the host had sole ownership of all of them. However, changing the state of those pages has clearly become a goal both to support vendor extensions to the hypervisor, as well as to support device assignment in the longer term. To pave the way towards this support, let's allow certain state transitions for MMIO pages. Bug: 264070847 Change-Id: I9803b572c90d8a694c3d43a0ee0d7b4f4124fe4a Signed-off-by: Quentin Perret --- arch/arm64/kvm/hyp/nvhe/mem_protect.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c index 9f71e226d95f..8bf6b8457a34 100644 --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c @@ -1018,7 +1018,7 @@ static enum pkvm_page_state host_get_page_state(kvm_pte_t pte, u64 addr) if (is_memory && hyp_phys_to_page(addr)->flags & MODULE_OWNED_PAGE) return PKVM_MODULE_DONT_TOUCH; - if (!addr_is_allowed_memory(addr)) + if (is_memory && !addr_is_allowed_memory(addr)) return PKVM_NOPAGE; if (!kvm_pte_valid(pte) && pte) @@ -1235,7 +1235,7 @@ static int hyp_ack_share(u64 addr, const struct pkvm_mem_transition *tx, phys_addr_t phys = hyp_virt_to_phys((void *)addr); enum kvm_pgtable_prot prot = default_hyp_prot(phys); - if (perms != prot) + if (!addr_is_memory(phys) || perms != prot) return -EPERM; if (__hyp_ack_skip_pgtable_check(tx)) @@ -1330,7 +1330,7 @@ static int guest_ack_share(u64 addr, const struct pkvm_mem_transition *tx, { u64 size = tx->nr_pages * PAGE_SIZE; - if (perms != KVM_PGTABLE_PROT_RWX) + if (!addr_is_memory(tx->completer.guest.phys) || perms != KVM_PGTABLE_PROT_RWX) return -EPERM; return __guest_check_page_state_range(tx->completer.guest.hyp_vcpu, @@ -1341,6 +1341,9 @@ static int guest_ack_donation(u64 addr, const struct pkvm_mem_transition *tx) { u64 size = tx->nr_pages * PAGE_SIZE; + if (!addr_is_memory(tx->completer.guest.phys)) + return -EPERM; + return __guest_check_page_state_range(tx->completer.guest.hyp_vcpu, addr, size, PKVM_NOPAGE); }