aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHuang Ying <ying.huang@intel.com>2011-01-29 22:15:48 -0500
committerMarcelo Tosatti <mtosatti@redhat.com>2011-03-17 12:08:27 -0400
commit69ebb83e13e514222b0ae4f8bd813a17679ed876 (patch)
tree62ccc7ee1e840d0a6cc01a9fc1c44a5f4e6f1edd
parent0014bd990e69063b0fb78940b35439d7980ce3ee (diff)
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: Huang Ying <ying.huang@intel.com> Cc: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--arch/alpha/include/asm/errno.h2
-rw-r--r--arch/mips/include/asm/errno.h2
-rw-r--r--arch/parisc/include/asm/errno.h2
-rw-r--r--arch/sparc/include/asm/errno.h2
-rw-r--r--include/asm-generic/errno.h2
-rw-r--r--include/linux/mm.h1
-rw-r--r--mm/memory.c13
7 files changed, 21 insertions, 3 deletions
diff --git a/arch/alpha/include/asm/errno.h b/arch/alpha/include/asm/errno.h
index 98099bda9370..e5f29ca28180 100644
--- a/arch/alpha/include/asm/errno.h
+++ b/arch/alpha/include/asm/errno.h
@@ -122,4 +122,6 @@
122 122
123#define ERFKILL 138 /* Operation not possible due to RF-kill */ 123#define ERFKILL 138 /* Operation not possible due to RF-kill */
124 124
125#define EHWPOISON 139 /* Memory page has hardware error */
126
125#endif 127#endif
diff --git a/arch/mips/include/asm/errno.h b/arch/mips/include/asm/errno.h
index a0efc73819e4..6dcd3583ed04 100644
--- a/arch/mips/include/asm/errno.h
+++ b/arch/mips/include/asm/errno.h
@@ -121,6 +121,8 @@
121 121
122#define ERFKILL 167 /* Operation not possible due to RF-kill */ 122#define ERFKILL 167 /* Operation not possible due to RF-kill */
123 123
124#define EHWPOISON 168 /* Memory page has hardware error */
125
124#define EDQUOT 1133 /* Quota exceeded */ 126#define EDQUOT 1133 /* Quota exceeded */
125 127
126#ifdef __KERNEL__ 128#ifdef __KERNEL__
diff --git a/arch/parisc/include/asm/errno.h b/arch/parisc/include/asm/errno.h
index 9992abdd782d..135ad6047e51 100644
--- a/arch/parisc/include/asm/errno.h
+++ b/arch/parisc/include/asm/errno.h
@@ -122,4 +122,6 @@
122 122
123#define ERFKILL 256 /* Operation not possible due to RF-kill */ 123#define ERFKILL 256 /* Operation not possible due to RF-kill */
124 124
125#define EHWPOISON 257 /* Memory page has hardware error */
126
125#endif 127#endif
diff --git a/arch/sparc/include/asm/errno.h b/arch/sparc/include/asm/errno.h
index 4e2bc490d714..c351aba997b7 100644
--- a/arch/sparc/include/asm/errno.h
+++ b/arch/sparc/include/asm/errno.h
@@ -112,4 +112,6 @@
112 112
113#define ERFKILL 134 /* Operation not possible due to RF-kill */ 113#define ERFKILL 134 /* Operation not possible due to RF-kill */
114 114
115#define EHWPOISON 135 /* Memory page has hardware error */
116
115#endif 117#endif
diff --git a/include/asm-generic/errno.h b/include/asm-generic/errno.h
index 28cc03bf19e6..a1331ce50445 100644
--- a/include/asm-generic/errno.h
+++ b/include/asm-generic/errno.h
@@ -108,4 +108,6 @@
108 108
109#define ERFKILL 132 /* Operation not possible due to RF-kill */ 109#define ERFKILL 132 /* Operation not possible due to RF-kill */
110 110
111#define EHWPOISON 133 /* Memory page has hardware error */
112
111#endif 113#endif
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 46150c66318e..a77c82c56e05 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1532,6 +1532,7 @@ struct page *follow_page(struct vm_area_struct *, unsigned long address,
1532#define FOLL_FORCE 0x10 /* get_user_pages read/write w/o permission */ 1532#define FOLL_FORCE 0x10 /* get_user_pages read/write w/o permission */
1533#define FOLL_MLOCK 0x40 /* mark page as mlocked */ 1533#define FOLL_MLOCK 0x40 /* mark page as mlocked */
1534#define FOLL_SPLIT 0x80 /* don't return transhuge pages, split them */ 1534#define FOLL_SPLIT 0x80 /* don't return transhuge pages, split them */
1535#define FOLL_HWPOISON 0x100 /* check page is hwpoisoned */
1535 1536
1536typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr, 1537typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr,
1537 void *data); 1538 void *data);
diff --git a/mm/memory.c b/mm/memory.c
index 806a37ec71bd..346ee7e041fd 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1576,9 +1576,16 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
1576 if (ret & VM_FAULT_ERROR) { 1576 if (ret & VM_FAULT_ERROR) {
1577 if (ret & VM_FAULT_OOM) 1577 if (ret & VM_FAULT_OOM)
1578 return i ? i : -ENOMEM; 1578 return i ? i : -ENOMEM;
1579 if (ret & 1579 if (ret & (VM_FAULT_HWPOISON |
1580 (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE| 1580 VM_FAULT_HWPOISON_LARGE)) {
1581 VM_FAULT_SIGBUS)) 1581 if (i)
1582 return i;
1583 else if (gup_flags & FOLL_HWPOISON)
1584 return -EHWPOISON;
1585 else
1586 return -EFAULT;
1587 }
1588 if (ret & VM_FAULT_SIGBUS)
1582 return i ? i : -EFAULT; 1589 return i ? i : -EFAULT;
1583 BUG(); 1590 BUG();
1584 } 1591 }