aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--virt/kvm/kvm_main.c11
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
1031static 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
1031static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic, 1040static 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(&current->mm->mmap_sem); 1086 down_read(&current->mm->mmap_sem);
1078 if (is_hwpoison_address(addr)) { 1087 if (check_user_page_hwpoison(addr)) {
1079 up_read(&current->mm->mmap_sem); 1088 up_read(&current->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);