From 2c06d861a9f3a08385948a9ddd55e9b2eaaee6dc Mon Sep 17 00:00:00 2001 From: Quentin Perret Date: Tue, 7 Jun 2022 12:00:07 +0000 Subject: [PATCH] ANDROID: KVM: arm64: Don't update IOMMUs unnecessarily When handling host stage-2 faults the hypervisor currently updates the CPU _and_ IOMMUs page-tables. However, since we currently proactively map accessible PA ranges into IOMMUs, updating them during stage-2 faults is unnecessary -- it only needs to be done during ownership transitions. Optimize this by skipping the IOMMU updates from the host memory abort path, which also reduces contention on the host stage-2 lock during boot and saves up to 1.1 sec of boot time on Pixel 6. Bug: 232879742 Change-Id: Icb6f1b2d10de8cc2f976bbc94b9b79ad7aaa6135 Signed-off-by: Quentin Perret (cherry picked from commit 20c6e1ba55403fad0e7f039cc5d7e6f8c0fffa50) Signed-off-by: Mostafa Saleh --- arch/arm64/kvm/hyp/include/nvhe/mem_protect.h | 3 ++- arch/arm64/kvm/hyp/nvhe/mem_protect.c | 14 ++++++++------ arch/arm64/kvm/hyp/nvhe/setup.c | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h index a42090ab120c..18109fc7cc4d 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h +++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h @@ -82,7 +82,8 @@ int __pkvm_host_share_ffa(u64 pfn, u64 nr_pages); int __pkvm_host_unshare_ffa(u64 pfn, u64 nr_pages); bool addr_is_memory(phys_addr_t phys); -int host_stage2_idmap_locked(phys_addr_t addr, u64 size, enum kvm_pgtable_prot prot); +int host_stage2_idmap_locked(phys_addr_t addr, u64 size, enum kvm_pgtable_prot prot, + bool update_iommu); int host_stage2_set_owner_locked(phys_addr_t addr, u64 size, u8 owner_id); int host_stage2_unmap_dev_locked(phys_addr_t start, u64 size); int kvm_host_prepare_stage2(void *pgt_pool_base); diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c index 0c3db72312ff..5c0aff3e7694 100644 --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c @@ -513,7 +513,8 @@ static bool range_is_memory(u64 start, u64 end) } static inline int __host_stage2_idmap(u64 start, u64 end, - enum kvm_pgtable_prot prot) + enum kvm_pgtable_prot prot, + bool update_iommu) { int ret; @@ -522,7 +523,8 @@ static inline int __host_stage2_idmap(u64 start, u64 end, if (ret) return ret; - pkvm_iommu_host_stage2_idmap(start, end, prot); + if (update_iommu) + pkvm_iommu_host_stage2_idmap(start, end, prot); return 0; } @@ -584,9 +586,9 @@ static int host_stage2_adjust_range(u64 addr, struct kvm_mem_range *range) } int host_stage2_idmap_locked(phys_addr_t addr, u64 size, - enum kvm_pgtable_prot prot) + enum kvm_pgtable_prot prot, bool update_iommu) { - return host_stage2_try(__host_stage2_idmap, addr, addr + size, prot); + return host_stage2_try(__host_stage2_idmap, addr, addr + size, prot, update_iommu); } #define KVM_INVALID_PTE_OWNER_MASK GENMASK(9, 2) @@ -664,7 +666,7 @@ static int host_stage2_idmap(u64 addr) if (ret) return ret; - return host_stage2_idmap_locked(range.start, range.end - range.start, prot); + return host_stage2_idmap_locked(range.start, range.end - range.start, prot, false); } static void host_inject_abort(struct kvm_cpu_context *host_ctxt) @@ -846,7 +848,7 @@ static int __host_set_page_state_range(u64 addr, u64 size, { enum kvm_pgtable_prot prot = pkvm_mkstate(PKVM_HOST_MEM_PROT, state); - return host_stage2_idmap_locked(addr, size, prot); + return host_stage2_idmap_locked(addr, size, prot, true); } static int host_request_owned_transition(u64 *completer_addr, diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setup.c index b10d903e05f2..66392411ecaa 100644 --- a/arch/arm64/kvm/hyp/nvhe/setup.c +++ b/arch/arm64/kvm/hyp/nvhe/setup.c @@ -248,7 +248,7 @@ static int fix_host_ownership_walker(u64 addr, u64 end, u32 level, return -EINVAL; } - return host_stage2_idmap_locked(phys, PAGE_SIZE, prot); + return host_stage2_idmap_locked(phys, PAGE_SIZE, prot, false); } static int fix_hyp_pgtable_refcnt_walker(u64 addr, u64 end, u32 level,