Commit 0857b9e95c1af8bfe84630ef6747b9d4d61de4c6
Committed by
Avi Kivity
1 parent
9e02fb9633
Exists in
master
and in
39 other branches
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: Gleb Natapov <gleb@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Showing 1 changed file with 21 additions and 2 deletions Side-by-side Diff
virt/kvm/kvm_main.c
... | ... | @@ -1037,6 +1037,17 @@ |
1037 | 1037 | return fault_pfn; |
1038 | 1038 | } |
1039 | 1039 | |
1040 | +int get_user_page_nowait(struct task_struct *tsk, struct mm_struct *mm, | |
1041 | + unsigned long start, int write, struct page **page) | |
1042 | +{ | |
1043 | + int flags = FOLL_TOUCH | FOLL_NOWAIT | FOLL_HWPOISON | FOLL_GET; | |
1044 | + | |
1045 | + if (write) | |
1046 | + flags |= FOLL_WRITE; | |
1047 | + | |
1048 | + return __get_user_pages(tsk, mm, start, 1, flags, page, NULL, NULL); | |
1049 | +} | |
1050 | + | |
1040 | 1051 | static inline int check_user_page_hwpoison(unsigned long addr) |
1041 | 1052 | { |
1042 | 1053 | int rc, flags = FOLL_TOUCH | FOLL_HWPOISON | FOLL_WRITE; |
... | ... | @@ -1070,7 +1081,14 @@ |
1070 | 1081 | if (writable) |
1071 | 1082 | *writable = write_fault; |
1072 | 1083 | |
1073 | - npages = get_user_pages_fast(addr, 1, write_fault, page); | |
1084 | + if (async) { | |
1085 | + down_read(¤t->mm->mmap_sem); | |
1086 | + npages = get_user_page_nowait(current, current->mm, | |
1087 | + addr, write_fault, page); | |
1088 | + up_read(¤t->mm->mmap_sem); | |
1089 | + } else | |
1090 | + npages = get_user_pages_fast(addr, 1, write_fault, | |
1091 | + page); | |
1074 | 1092 | |
1075 | 1093 | /* map read fault as writable if possible */ |
1076 | 1094 | if (unlikely(!write_fault) && npages == 1) { |
... | ... | @@ -1093,7 +1111,8 @@ |
1093 | 1111 | return get_fault_pfn(); |
1094 | 1112 | |
1095 | 1113 | down_read(¤t->mm->mmap_sem); |
1096 | - if (check_user_page_hwpoison(addr)) { | |
1114 | + if (npages == -EHWPOISON || | |
1115 | + (!async && check_user_page_hwpoison(addr))) { | |
1097 | 1116 | up_read(¤t->mm->mmap_sem); |
1098 | 1117 | get_page(hwpoison_page); |
1099 | 1118 | return page_to_pfn(hwpoison_page); |