diff options
-rw-r--r-- | virt/kvm/kvm_main.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 4856a7dcbd7f..002fe0b12c9f 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -1028,6 +1028,15 @@ static pfn_t get_fault_pfn(void) | |||
1028 | return fault_pfn; | 1028 | return fault_pfn; |
1029 | } | 1029 | } |
1030 | 1030 | ||
1031 | static inline int check_user_page_hwpoison(unsigned long addr) | ||
1032 | { | ||
1033 | int rc, flags = FOLL_TOUCH | FOLL_HWPOISON | FOLL_WRITE; | ||
1034 | |||
1035 | rc = __get_user_pages(current, current->mm, addr, 1, | ||
1036 | flags, NULL, NULL, NULL); | ||
1037 | return rc == -EHWPOISON; | ||
1038 | } | ||
1039 | |||
1031 | static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic, | 1040 | static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic, |
1032 | bool *async, bool write_fault, bool *writable) | 1041 | bool *async, bool write_fault, bool *writable) |
1033 | { | 1042 | { |
@@ -1075,7 +1084,7 @@ static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic, | |||
1075 | return get_fault_pfn(); | 1084 | return get_fault_pfn(); |
1076 | 1085 | ||
1077 | down_read(¤t->mm->mmap_sem); | 1086 | down_read(¤t->mm->mmap_sem); |
1078 | if (is_hwpoison_address(addr)) { | 1087 | if (check_user_page_hwpoison(addr)) { |
1079 | up_read(¤t->mm->mmap_sem); | 1088 | up_read(¤t->mm->mmap_sem); |
1080 | get_page(hwpoison_page); | 1089 | get_page(hwpoison_page); |
1081 | return page_to_pfn(hwpoison_page); | 1090 | return page_to_pfn(hwpoison_page); |