ANDROID: KVM: arm64: Map MMIO in guest abort path

Allow devices MMIO to be mapped in guest abort path, to avoid
impacting the hot path of normal memory add the device check in
the fail path of memory pinning.

Bug: 357781595
Bug: 348382247
Change-Id: I2d2aae9882128b80df723042a1b6a1ce43330cd6
Signed-off-by: Mostafa Saleh <smostafa@google.com>
This commit is contained in:
Mostafa Saleh
2024-07-08 12:38:42 +00:00
committed by Treehugger Robot
parent 4a1c027130
commit e0a0783241
+32
View File
@@ -1716,6 +1716,11 @@ static int pkvm_relax_perms(struct kvm_vcpu *vcpu, u64 pfn, u64 gfn, u8 order,
(void *)prot, false);
}
static int pkvm_mem_abort_device(struct kvm *kvm, u64 pfn, u64 gfn)
{
return kvm_call_hyp_nvhe(__pkvm_host_map_guest_mmio, pfn, gfn);
}
static int pkvm_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t *fault_ipa,
struct kvm_memory_slot *memslot, size_t *size)
{
@@ -1751,6 +1756,33 @@ static int pkvm_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t *fault_ipa,
if (ret == -EHWPOISON) {
kvm_send_hwpoison_signal(hva, PAGE_SHIFT);
ret = 0;
goto free_ppage;
} else if (ret == -EFAULT) {
/*
* pKVM relies on pinning the page then getting the pfn from there to map it,
* However, to avoid adding overhead on the hot path with checking pfn first,
* device check is done on the fail path for pin_user_pages, inside -EFAULT
* case, that possible is because the VMA for the device mapping is VM_IO,
* which fails in check_vma_flags() with -EFAULT
*/
bool device;
pfn = __gfn_to_pfn_memslot(memslot, gfn, false, false, NULL,
kvm_is_write_fault(vcpu), NULL, NULL);
if (is_error_noslot_pfn(pfn))
goto free_ppage;
device = kvm_is_device_pfn(pfn);
if (device) {
ret = pkvm_mem_abort_device(kvm, pfn, gfn);
if (ret == -EEXIST)
ret = 0; /* We might have raced with another vCPU. */
else if (!ret && size)
*size = PAGE_SIZE;
} else {
/* Release pin from __gfn_to_pfn_memslot(). */
kvm_release_pfn_clean(pfn);
}
goto free_ppage;
} else if (ret != 1) {
ret = -EFAULT;