/* * Attempt to pin the VM's host address space, and simply skip gup() if * acquiring a pin fail, i.e. if the process is exiting. Note, KVM * holds a reference to its associated mm_struct until the very end of * kvm_destroy_vm(), i.e. the struct itself won't be freed before this * work item is fully processed.
*/ if (mmget_not_zero(mm)) {
mmap_read_lock(mm);
get_user_pages_remote(mm, addr, 1, FOLL_WRITE, NULL, &locked); if (locked)
mmap_read_unlock(mm);
mmput(mm);
}
/* * Notify and kick the vCPU even if faulting in the page failed, e.g. * so that the vCPU can retry the fault synchronously.
*/ if (IS_ENABLED(CONFIG_KVM_ASYNC_PF_SYNC))
kvm_arch_async_page_present(vcpu, apf);
spin_lock(&vcpu->async_pf.lock);
first = list_empty(&vcpu->async_pf.done);
list_add_tail(&apf->link, &vcpu->async_pf.done);
spin_unlock(&vcpu->async_pf.lock);
/* * The apf struct may be freed by kvm_check_async_pf_completion() as * soon as the lock is dropped. Nullify it to prevent improper usage.
*/
apf = NULL;
if (!IS_ENABLED(CONFIG_KVM_ASYNC_PF_SYNC) && first)
kvm_arch_async_page_present_queued(vcpu);
trace_kvm_async_pf_completed(addr, cr2_or_gpa);
__kvm_vcpu_wake_up(vcpu);
}
staticvoid kvm_flush_and_free_async_pf_work(struct kvm_async_pf *work)
{ /* * The async #PF is "done", but KVM must wait for the work item itself, * i.e. async_pf_execute(), to run to completion. If KVM is a module, * KVM must ensure *no* code owned by the KVM (the module) can be run * after the last call to module_put(). Note, flushing the work item * is always required when the item is taken off the completion queue. * E.g. even if the vCPU handles the item in the "normal" path, the VM * could be terminated before async_pf_execute() completes. * * Wake all events skip the queue and go straight done, i.e. don't * need to be flushed (but sanity check that the work wasn't queued).
*/ if (work->wakeup_all)
WARN_ON_ONCE(work->work.func); else
flush_work(&work->work);
kmem_cache_free(async_pf_cache, work);
}
/* * Try to schedule a job to handle page fault asynchronously. Returns 'true' on * success, 'false' on failure (page fault has to be handled synchronously).
*/ bool kvm_setup_async_pf(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, unsignedlong hva, struct kvm_arch_async_pf *arch)
{ struct kvm_async_pf *work;
if (vcpu->async_pf.queued >= ASYNC_PF_PER_VCPU) returnfalse;
/* Arch specific code should not do async PF in this case */ if (unlikely(kvm_is_error_hva(hva))) returnfalse;
/* * do alloc nowait since if we are going to sleep anyway we * may as well sleep faulting in page
*/
work = kmem_cache_zalloc(async_pf_cache, GFP_NOWAIT | __GFP_NOWARN); if (!work) returnfalse;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.