Commit 0857b9e9 authored by Gleb Natapov's avatar Gleb Natapov Committed by Avi Kivity

KVM: Enable async page fault processing

If asynchronous hva_to_pfn() is requested call GUP with FOLL_NOWAIT to
avoid sleeping on IO. Check for hwpoison is done at the same time,
otherwise check_user_page_hwpoison() will call GUP again and will put
vcpu to sleep.
Signed-off-by: default avatarGleb Natapov <gleb@redhat.com>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 9e02fb96
...@@ -1037,6 +1037,17 @@ static pfn_t get_fault_pfn(void) ...@@ -1037,6 +1037,17 @@ static pfn_t get_fault_pfn(void)
return fault_pfn; return fault_pfn;
} }
int get_user_page_nowait(struct task_struct *tsk, struct mm_struct *mm,
unsigned long start, int write, struct page **page)
{
int flags = FOLL_TOUCH | FOLL_NOWAIT | FOLL_HWPOISON | FOLL_GET;
if (write)
flags |= FOLL_WRITE;
return __get_user_pages(tsk, mm, start, 1, flags, page, NULL, NULL);
}
static inline int check_user_page_hwpoison(unsigned long addr) static inline int check_user_page_hwpoison(unsigned long addr)
{ {
int rc, flags = FOLL_TOUCH | FOLL_HWPOISON | FOLL_WRITE; int rc, flags = FOLL_TOUCH | FOLL_HWPOISON | FOLL_WRITE;
...@@ -1070,7 +1081,14 @@ static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic, ...@@ -1070,7 +1081,14 @@ static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic,
if (writable) if (writable)
*writable = write_fault; *writable = write_fault;
npages = get_user_pages_fast(addr, 1, write_fault, page); if (async) {
down_read(&current->mm->mmap_sem);
npages = get_user_page_nowait(current, current->mm,
addr, write_fault, page);
up_read(&current->mm->mmap_sem);
} else
npages = get_user_pages_fast(addr, 1, write_fault,
page);
/* map read fault as writable if possible */ /* map read fault as writable if possible */
if (unlikely(!write_fault) && npages == 1) { if (unlikely(!write_fault) && npages == 1) {
...@@ -1093,7 +1111,8 @@ static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic, ...@@ -1093,7 +1111,8 @@ static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic,
return get_fault_pfn(); return get_fault_pfn();
down_read(&current->mm->mmap_sem); down_read(&current->mm->mmap_sem);
if (check_user_page_hwpoison(addr)) { if (npages == -EHWPOISON ||
(!async && check_user_page_hwpoison(addr))) {
up_read(&current->mm->mmap_sem); up_read(&current->mm->mmap_sem);
get_page(hwpoison_page); get_page(hwpoison_page);
return page_to_pfn(hwpoison_page); return page_to_pfn(hwpoison_page);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment