From d9eeae6046081bf353808af2eb5636e9b9c019ec Mon Sep 17 00:00:00 2001 From: Sebastian Ene Date: Wed, 29 Jan 2025 16:42:41 +0000 Subject: [PATCH] ANDROID: KVM: arm64: Support pVM memory sharing with Trustzone(FF-A) Store an annotation inside the guest stage-2 pagetables to mark the memory as shared with FF-A. The memory transitions from the OWNED state to SHARED_OWNED. Return the PA corresponding to the page that we want to share to prevent additional walks. Bug: 269285339 Bug: 278749606 Change-Id: I5bdd51824ceffb4a891f2e97b62cc5af4460e542 Signed-off-by: Sebastian Ene --- arch/arm64/kvm/hyp/include/nvhe/mem_protect.h | 2 + arch/arm64/kvm/hyp/nvhe/mem_protect.c | 44 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h index c37af4366d78..1016fd70ba50 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h +++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h @@ -47,6 +47,8 @@ int __pkvm_host_donate_hyp_locked(u64 pfn, u64 nr_pages, enum kvm_pgtable_prot p int __pkvm_hyp_donate_host(u64 pfn, u64 nr_pages); int __pkvm_guest_share_hyp_page(struct pkvm_hyp_vcpu *vcpu, u64 ipa, u64 *hyp_va); int __pkvm_guest_unshare_hyp_page(struct pkvm_hyp_vcpu *vcpu, u64 ipa); +int __pkvm_guest_share_ffa_page(struct pkvm_hyp_vcpu *vcpu, u64 ipa, phys_addr_t *phys); +int __pkvm_guest_unshare_ffa_page(struct pkvm_hyp_vcpu *vcpu, u64 ipa); int __pkvm_host_share_ffa(u64 pfn, u64 nr_pages); int __pkvm_host_unshare_ffa(u64 pfn, u64 nr_pages); int __pkvm_host_donate_guest(u64 pfn, u64 gfn, struct pkvm_hyp_vcpu *vcpu, u64 nr_pages); diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c index 64cdaa64b09b..acce20afcd5f 100644 --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c @@ -1457,6 +1457,50 @@ unlock: return ret; } +int __pkvm_guest_share_ffa_page(struct pkvm_hyp_vcpu *vcpu, u64 ipa, phys_addr_t *phys) +{ + int ret; + struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(vcpu); + kvm_pte_t pte; + u64 nr_pages = 1; + + guest_lock_component(vm); + ret = __guest_request_page_transition(ipa, &pte, &nr_pages, vcpu, PKVM_PAGE_OWNED); + if (ret) + goto unlock; + + ret = __guest_initiate_page_transition(ipa, pte, nr_pages, vcpu, PKVM_PAGE_SHARED_OWNED); + if (!ret) + *phys = kvm_pte_to_phys(pte); +unlock: + guest_unlock_component(vm); + + return ret; +} + +/* + * The caller is responsible for tracking the FFA state and this function + * should only be called for IPAs that have previously been shared with FFA. + */ +int __pkvm_guest_unshare_ffa_page(struct pkvm_hyp_vcpu *vcpu, u64 ipa) +{ + int ret; + struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(vcpu); + kvm_pte_t pte; + u64 nr_pages = 1; + + guest_lock_component(vm); + ret = __guest_request_page_transition(ipa, &pte, &nr_pages, vcpu, PKVM_PAGE_SHARED_OWNED); + if (ret) + goto unlock; + + ret = __guest_initiate_page_transition(ipa, pte, nr_pages, vcpu, PKVM_PAGE_OWNED); +unlock: + guest_unlock_component(vm); + + return ret; +} + int __pkvm_host_donate_hyp(u64 pfn, u64 nr_pages) { return ___pkvm_host_donate_hyp(pfn, nr_pages, false);