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 <qperret@google.com>
(cherry picked from commit 20c6e1ba55)
Signed-off-by: Mostafa Saleh <smostafa@google.com>
This commit is contained in:
Quentin Perret
2022-06-07 12:00:07 +00:00
committed by Mostafa Saleh
parent 0812877eff
commit 2c06d861a9
3 changed files with 11 additions and 8 deletions

View File

@@ -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);

View File

@@ -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,

View File

@@ -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,