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: 357781595 Bug: 384432312 Change-Id: Icb6f1b2d10de8cc2f976bbc94b9b79ad7aaa6135 Signed-off-by: Quentin Perret <qperret@google.com> (cherry picked from commit 20c6e1ba55403fad0e7f039cc5d7e6f8c0fffa50) Signed-off-by: Mostafa Saleh <smostafa@google.com>
This commit is contained in:
committed by
Mostafa Saleh
parent
a09f1819c5
commit
09a2d1b37e
@@ -64,7 +64,9 @@ int __pkvm_host_use_dma(u64 phys_addr, size_t size);
|
||||
int __pkvm_host_unuse_dma(u64 phys_addr, size_t size);
|
||||
|
||||
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_reg_locked(phys_addr_t start, u64 size);
|
||||
int kvm_host_prepare_stage2(void *pgt_pool_base);
|
||||
|
||||
@@ -159,7 +159,7 @@ static int prepopulate_host_stage2(void)
|
||||
|
||||
for (i = 0; i < hyp_memblock_nr; i++) {
|
||||
reg = &hyp_memory[i];
|
||||
ret = host_stage2_idmap_locked(reg->base, reg->size, PKVM_HOST_MEM_PROT);
|
||||
ret = host_stage2_idmap_locked(reg->base, reg->size, PKVM_HOST_MEM_PROT, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@@ -549,7 +549,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;
|
||||
|
||||
@@ -558,7 +559,8 @@ static inline int __host_stage2_idmap(u64 start, u64 end,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
kvm_iommu_host_stage2_idmap(start, end, prot);
|
||||
if (update_iommu)
|
||||
kvm_iommu_host_stage2_idmap(start, end, prot);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -623,9 +625,10 @@ 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_MAX_OWNER_ID FIELD_MAX(KVM_INVALID_PTE_OWNER_MASK)
|
||||
@@ -655,7 +658,7 @@ static int __host_stage2_set_owner_locked(phys_addr_t addr, u64 size, u8 owner_i
|
||||
|
||||
if (owner_id == PKVM_ID_HOST) {
|
||||
prot = default_host_prot(addr_is_memory(addr));
|
||||
ret = host_stage2_idmap_locked(addr, size, prot);
|
||||
ret = host_stage2_idmap_locked(addr, size, prot, false);
|
||||
} else {
|
||||
annotation = kvm_init_invalid_leaf_owner(owner_id);
|
||||
ret = host_stage2_try(kvm_pgtable_stage2_annotate,
|
||||
@@ -725,13 +728,14 @@ static int host_stage2_idmap(u64 addr)
|
||||
bool is_memory = !!find_mem_range(addr, &range);
|
||||
enum kvm_pgtable_prot prot = default_host_prot(is_memory);
|
||||
int ret;
|
||||
bool update_iommu = !is_memory;
|
||||
|
||||
host_lock_component();
|
||||
ret = host_stage2_adjust_range(addr, &range);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
ret = host_stage2_idmap_locked(range.start, range.end - range.start, prot);
|
||||
ret = host_stage2_idmap_locked(range.start, range.end - range.start, prot, update_iommu);
|
||||
unlock:
|
||||
host_unlock_component();
|
||||
|
||||
@@ -1016,7 +1020,7 @@ static int __host_set_page_state_range(u64 addr, u64 size,
|
||||
enum pkvm_page_state state)
|
||||
{
|
||||
if (hyp_phys_to_page(addr)->host_state & PKVM_NOPAGE) {
|
||||
int ret = host_stage2_idmap_locked(addr, size, PKVM_HOST_MEM_PROT);
|
||||
int ret = host_stage2_idmap_locked(addr, size, PKVM_HOST_MEM_PROT, true);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -2054,7 +2058,7 @@ update:
|
||||
PKVM_MODULE_OWNED_PAGE);
|
||||
} else {
|
||||
ret = host_stage2_idmap_locked(
|
||||
addr, nr_pages << PAGE_SHIFT, prot);
|
||||
addr, nr_pages << PAGE_SHIFT, prot, false);
|
||||
}
|
||||
|
||||
if (WARN_ON(ret) || !page || !prot)
|
||||
|
||||
Reference in New Issue
Block a user