Skip to content

Commit

Permalink
KVM: Drop FOLL_GET in GUP when doing async page fault
Browse files Browse the repository at this point in the history
Page pinning is not mandatory in kvm async page fault processing since
after async page fault event is delivered to a guest it accesses page once
again and does its own GUP.  Drop the FOLL_GET flag in GUP in async_pf
code, and do some simplifying in check/clear processing.

Suggested-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Gu zheng <guz.fnst@cn.fujitsu.com>
Signed-off-by: chai wen <chaiw.fnst@cn.fujitsu.com>
Signed-off-by: Gleb Natapov <gleb@redhat.com>
  • Loading branch information
chai wen authored and Gleb Natapov committed Oct 15, 2013
1 parent a7efdf6 commit f2e1066
Show file tree
Hide file tree
Showing 4 changed files with 12 additions and 21 deletions.
4 changes: 2 additions & 2 deletions arch/x86/kvm/x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -7298,7 +7298,7 @@ void kvm_arch_async_page_ready(struct kvm_vcpu *vcpu, struct kvm_async_pf *work)
int r;

if ((vcpu->arch.mmu.direct_map != work->arch.direct_map) ||
is_error_page(work->page))
work->wakeup_all)
return;

r = kvm_mmu_reload(vcpu);
Expand Down Expand Up @@ -7408,7 +7408,7 @@ void kvm_arch_async_page_present(struct kvm_vcpu *vcpu,
struct x86_exception fault;

trace_kvm_async_pf_ready(work->arch.token, work->gva);
if (is_error_page(work->page))
if (work->wakeup_all)
work->arch.token = ~0; /* broadcast wakeup */
else
kvm_del_async_pf_gfn(vcpu, work->arch.gfn);
Expand Down
2 changes: 1 addition & 1 deletion include/linux/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ struct kvm_async_pf {
gva_t gva;
unsigned long addr;
struct kvm_arch_async_pf arch;
struct page *page;
bool wakeup_all;
};

void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu);
Expand Down
10 changes: 4 additions & 6 deletions include/trace/events/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -296,23 +296,21 @@ DEFINE_EVENT(kvm_async_pf_nopresent_ready, kvm_async_pf_ready,

TRACE_EVENT(
kvm_async_pf_completed,
TP_PROTO(unsigned long address, struct page *page, u64 gva),
TP_ARGS(address, page, gva),
TP_PROTO(unsigned long address, u64 gva),
TP_ARGS(address, gva),

TP_STRUCT__entry(
__field(unsigned long, address)
__field(pfn_t, pfn)
__field(u64, gva)
),

TP_fast_assign(
__entry->address = address;
__entry->pfn = page ? page_to_pfn(page) : 0;
__entry->gva = gva;
),

TP_printk("gva %#llx address %#lx pfn %#llx", __entry->gva,
__entry->address, __entry->pfn)
TP_printk("gva %#llx address %#lx", __entry->gva,
__entry->address)
);

#endif
Expand Down
17 changes: 5 additions & 12 deletions virt/kvm/async_pf.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ void kvm_async_pf_vcpu_init(struct kvm_vcpu *vcpu)

static void async_pf_execute(struct work_struct *work)
{
struct page *page = NULL;
struct kvm_async_pf *apf =
container_of(work, struct kvm_async_pf, work);
struct mm_struct *mm = apf->mm;
Expand All @@ -68,21 +67,20 @@ static void async_pf_execute(struct work_struct *work)

use_mm(mm);
down_read(&mm->mmap_sem);
get_user_pages(current, mm, addr, 1, 1, 0, &page, NULL);
get_user_pages(current, mm, addr, 1, 1, 0, NULL, NULL);
up_read(&mm->mmap_sem);
unuse_mm(mm);

spin_lock(&vcpu->async_pf.lock);
list_add_tail(&apf->link, &vcpu->async_pf.done);
apf->page = page;
spin_unlock(&vcpu->async_pf.lock);

/*
* apf may be freed by kvm_check_async_pf_completion() after
* this point
*/

trace_kvm_async_pf_completed(addr, page, gva);
trace_kvm_async_pf_completed(addr, gva);

if (waitqueue_active(&vcpu->wq))
wake_up_interruptible(&vcpu->wq);
Expand Down Expand Up @@ -112,8 +110,6 @@ void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu)
list_entry(vcpu->async_pf.done.next,
typeof(*work), link);
list_del(&work->link);
if (!is_error_page(work->page))
kvm_release_page_clean(work->page);
kmem_cache_free(async_pf_cache, work);
}
spin_unlock(&vcpu->async_pf.lock);
Expand All @@ -133,14 +129,11 @@ void kvm_check_async_pf_completion(struct kvm_vcpu *vcpu)
list_del(&work->link);
spin_unlock(&vcpu->async_pf.lock);

if (work->page)
kvm_arch_async_page_ready(vcpu, work);
kvm_arch_async_page_ready(vcpu, work);
kvm_arch_async_page_present(vcpu, work);

list_del(&work->queue);
vcpu->async_pf.queued--;
if (!is_error_page(work->page))
kvm_release_page_clean(work->page);
kmem_cache_free(async_pf_cache, work);
}
}
Expand All @@ -163,7 +156,7 @@ int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn,
if (!work)
return 0;

work->page = NULL;
work->wakeup_all = false;
work->vcpu = vcpu;
work->gva = gva;
work->addr = gfn_to_hva(vcpu->kvm, gfn);
Expand Down Expand Up @@ -203,7 +196,7 @@ int kvm_async_pf_wakeup_all(struct kvm_vcpu *vcpu)
if (!work)
return -ENOMEM;

work->page = KVM_ERR_PTR_BAD_PAGE;
work->wakeup_all = true;
INIT_LIST_HEAD(&work->queue); /* for list_del to work */

spin_lock(&vcpu->async_pf.lock);
Expand Down

0 comments on commit f2e1066

Please sign in to comment.