Commit 69ebb83e authored by Huang Ying's avatar Huang Ying Committed by Marcelo Tosatti

mm: make __get_user_pages return -EHWPOISON for HWPOISON page optionally

Make __get_user_pages return -EHWPOISON for HWPOISON page only if
FOLL_HWPOISON is specified.  With this patch, the interested callers
can distinguish HWPOISON pages from general FAULT pages, while other
callers will still get -EFAULT for all these pages, so the user space
interface need not to be changed.

This feature is needed by KVM, where UCR MCE should be relayed to
guest for HWPOISON page, while instruction emulation and MMIO will be
tried for general FAULT page.

The idea comes from Andrew Morton.
Signed-off-by: default avatarHuang Ying <ying.huang@intel.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarMarcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 0014bd99
...@@ -122,4 +122,6 @@ ...@@ -122,4 +122,6 @@
#define ERFKILL 138 /* Operation not possible due to RF-kill */ #define ERFKILL 138 /* Operation not possible due to RF-kill */
#define EHWPOISON 139 /* Memory page has hardware error */
#endif #endif
...@@ -121,6 +121,8 @@ ...@@ -121,6 +121,8 @@
#define ERFKILL 167 /* Operation not possible due to RF-kill */ #define ERFKILL 167 /* Operation not possible due to RF-kill */
#define EHWPOISON 168 /* Memory page has hardware error */
#define EDQUOT 1133 /* Quota exceeded */ #define EDQUOT 1133 /* Quota exceeded */
#ifdef __KERNEL__ #ifdef __KERNEL__
......
...@@ -122,4 +122,6 @@ ...@@ -122,4 +122,6 @@
#define ERFKILL 256 /* Operation not possible due to RF-kill */ #define ERFKILL 256 /* Operation not possible due to RF-kill */
#define EHWPOISON 257 /* Memory page has hardware error */
#endif #endif
...@@ -112,4 +112,6 @@ ...@@ -112,4 +112,6 @@
#define ERFKILL 134 /* Operation not possible due to RF-kill */ #define ERFKILL 134 /* Operation not possible due to RF-kill */
#define EHWPOISON 135 /* Memory page has hardware error */
#endif #endif
...@@ -108,4 +108,6 @@ ...@@ -108,4 +108,6 @@
#define ERFKILL 132 /* Operation not possible due to RF-kill */ #define ERFKILL 132 /* Operation not possible due to RF-kill */
#define EHWPOISON 133 /* Memory page has hardware error */
#endif #endif
...@@ -1532,6 +1532,7 @@ struct page *follow_page(struct vm_area_struct *, unsigned long address, ...@@ -1532,6 +1532,7 @@ struct page *follow_page(struct vm_area_struct *, unsigned long address,
#define FOLL_FORCE 0x10 /* get_user_pages read/write w/o permission */ #define FOLL_FORCE 0x10 /* get_user_pages read/write w/o permission */
#define FOLL_MLOCK 0x40 /* mark page as mlocked */ #define FOLL_MLOCK 0x40 /* mark page as mlocked */
#define FOLL_SPLIT 0x80 /* don't return transhuge pages, split them */ #define FOLL_SPLIT 0x80 /* don't return transhuge pages, split them */
#define FOLL_HWPOISON 0x100 /* check page is hwpoisoned */
typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr, typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr,
void *data); void *data);
......
...@@ -1576,9 +1576,16 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, ...@@ -1576,9 +1576,16 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
if (ret & VM_FAULT_ERROR) { if (ret & VM_FAULT_ERROR) {
if (ret & VM_FAULT_OOM) if (ret & VM_FAULT_OOM)
return i ? i : -ENOMEM; return i ? i : -ENOMEM;
if (ret & if (ret & (VM_FAULT_HWPOISON |
(VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE| VM_FAULT_HWPOISON_LARGE)) {
VM_FAULT_SIGBUS)) if (i)
return i;
else if (gup_flags & FOLL_HWPOISON)
return -EHWPOISON;
else
return -EFAULT;
}
if (ret & VM_FAULT_SIGBUS)
return i ? i : -EFAULT; return i ? i : -EFAULT;
BUG(); BUG();
} }
......
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