2019-01-08 18:29:15

by Souptick Joarder

[permalink] [raw]
Subject: [PATCH v4] mm: Create the new vm_fault_t type

Page fault handlers are supposed to return VM_FAULT codes,
but some drivers/file systems mistakenly return error
numbers. Now that all drivers/file systems have been converted
to use the vm_fault_t return type, change the type definition
to no longer be compatible with 'int'. By making it an unsigned
int, the function prototype becomes incompatible with a function
which returns int. Sparse will detect any attempts to return a
value which is not a VM_FAULT code.

VM_FAULT_SET_HINDEX and VM_FAULT_GET_HINDEX values are changed
to avoid conflict with other VM_FAULT codes.

Signed-off-by: Souptick Joarder <[email protected]>
Reviewed-by: William Kucharski <[email protected]>
Reviewed-by: Mike Rapoport <[email protected]>
---
v2: Updated the change log and corrected the document part.
name added to the enum that kernel-doc able to parse it.

v3: Corrected the documentation.

v4: Reviewed by William and Mike ( for docs part).

include/linux/mm.h | 46 ------------------------------
include/linux/mm_types.h | 73 +++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 72 insertions(+), 47 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index fcf9cc9..511a3ce 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1267,52 +1267,6 @@ static inline void clear_page_pfmemalloc(struct page *page)
}

/*
- * Different kinds of faults, as returned by handle_mm_fault().
- * Used to decide whether a process gets delivered SIGBUS or
- * just gets major/minor fault counters bumped up.
- */
-
-#define VM_FAULT_OOM 0x0001
-#define VM_FAULT_SIGBUS 0x0002
-#define VM_FAULT_MAJOR 0x0004
-#define VM_FAULT_WRITE 0x0008 /* Special case for get_user_pages */
-#define VM_FAULT_HWPOISON 0x0010 /* Hit poisoned small page */
-#define VM_FAULT_HWPOISON_LARGE 0x0020 /* Hit poisoned large page. Index encoded in upper bits */
-#define VM_FAULT_SIGSEGV 0x0040
-
-#define VM_FAULT_NOPAGE 0x0100 /* ->fault installed the pte, not return page */
-#define VM_FAULT_LOCKED 0x0200 /* ->fault locked the returned page */
-#define VM_FAULT_RETRY 0x0400 /* ->fault blocked, must retry */
-#define VM_FAULT_FALLBACK 0x0800 /* huge page fault failed, fall back to small */
-#define VM_FAULT_DONE_COW 0x1000 /* ->fault has fully handled COW */
-#define VM_FAULT_NEEDDSYNC 0x2000 /* ->fault did not modify page tables
- * and needs fsync() to complete (for
- * synchronous page faults in DAX) */
-
-#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | \
- VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE | \
- VM_FAULT_FALLBACK)
-
-#define VM_FAULT_RESULT_TRACE \
- { VM_FAULT_OOM, "OOM" }, \
- { VM_FAULT_SIGBUS, "SIGBUS" }, \
- { VM_FAULT_MAJOR, "MAJOR" }, \
- { VM_FAULT_WRITE, "WRITE" }, \
- { VM_FAULT_HWPOISON, "HWPOISON" }, \
- { VM_FAULT_HWPOISON_LARGE, "HWPOISON_LARGE" }, \
- { VM_FAULT_SIGSEGV, "SIGSEGV" }, \
- { VM_FAULT_NOPAGE, "NOPAGE" }, \
- { VM_FAULT_LOCKED, "LOCKED" }, \
- { VM_FAULT_RETRY, "RETRY" }, \
- { VM_FAULT_FALLBACK, "FALLBACK" }, \
- { VM_FAULT_DONE_COW, "DONE_COW" }, \
- { VM_FAULT_NEEDDSYNC, "NEEDDSYNC" }
-
-/* Encode hstate index for a hwpoisoned large page */
-#define VM_FAULT_SET_HINDEX(x) ((x) << 12)
-#define VM_FAULT_GET_HINDEX(x) (((x) >> 12) & 0xf)
-
-/*
* Can be called by the pagefault handler when it gets a VM_FAULT_OOM.
*/
extern void pagefault_out_of_memory(void);
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 5ed8f62..cb25016 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -22,7 +22,6 @@
#endif
#define AT_VECTOR_SIZE (2*(AT_VECTOR_SIZE_ARCH + AT_VECTOR_SIZE_BASE + 1))

-typedef int vm_fault_t;

struct address_space;
struct mem_cgroup;
@@ -609,6 +608,78 @@ static inline bool mm_tlb_flush_nested(struct mm_struct *mm)

struct vm_fault;

+/**
+ * typedef vm_fault_t - Return type for page fault handlers.
+ *
+ * Page fault handlers return a bitmask of %VM_FAULT values.
+ */
+typedef __bitwise unsigned int vm_fault_t;
+
+/**
+ * enum vm_fault_reason - Page fault handlers return a bitmask of
+ * these values to tell the core VM what happened when handling the
+ * fault. Used to decide whether a process gets delivered SIGBUS or
+ * just gets major/minor fault counters bumped up.
+ *
+ * @VM_FAULT_OOM: Out Of Memory
+ * @VM_FAULT_SIGBUS: Bad access
+ * @VM_FAULT_MAJOR: Page read from storage
+ * @VM_FAULT_WRITE: Special case for get_user_pages
+ * @VM_FAULT_HWPOISON: Hit poisoned small page
+ * @VM_FAULT_HWPOISON_LARGE: Hit poisoned large page. Index encoded
+ * in upper bits
+ * @VM_FAULT_SIGSEGV: segmentation fault
+ * @VM_FAULT_NOPAGE: ->fault installed the pte, not return page
+ * @VM_FAULT_LOCKED: ->fault locked the returned page
+ * @VM_FAULT_RETRY: ->fault blocked, must retry
+ * @VM_FAULT_FALLBACK: huge page fault failed, fall back to small
+ * @VM_FAULT_DONE_COW: ->fault has fully handled COW
+ * @VM_FAULT_NEEDDSYNC: ->fault did not modify page tables and needs
+ * fsync() to complete (for synchronous page faults
+ * in DAX)
+ * @VM_FAULT_HINDEX_MASK: mask HINDEX value
+ *
+ */
+enum vm_fault_reason {
+ VM_FAULT_OOM = (__force vm_fault_t)0x000001,
+ VM_FAULT_SIGBUS = (__force vm_fault_t)0x000002,
+ VM_FAULT_MAJOR = (__force vm_fault_t)0x000004,
+ VM_FAULT_WRITE = (__force vm_fault_t)0x000008,
+ VM_FAULT_HWPOISON = (__force vm_fault_t)0x000010,
+ VM_FAULT_HWPOISON_LARGE = (__force vm_fault_t)0x000020,
+ VM_FAULT_SIGSEGV = (__force vm_fault_t)0x000040,
+ VM_FAULT_NOPAGE = (__force vm_fault_t)0x000100,
+ VM_FAULT_LOCKED = (__force vm_fault_t)0x000200,
+ VM_FAULT_RETRY = (__force vm_fault_t)0x000400,
+ VM_FAULT_FALLBACK = (__force vm_fault_t)0x000800,
+ VM_FAULT_DONE_COW = (__force vm_fault_t)0x001000,
+ VM_FAULT_NEEDDSYNC = (__force vm_fault_t)0x002000,
+ VM_FAULT_HINDEX_MASK = (__force vm_fault_t)0x0f0000,
+};
+
+/* Encode hstate index for a hwpoisoned large page */
+#define VM_FAULT_SET_HINDEX(x) ((__force vm_fault_t)((x) << 16))
+#define VM_FAULT_GET_HINDEX(x) (((x) >> 16) & 0xf)
+
+#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | \
+ VM_FAULT_SIGSEGV | VM_FAULT_HWPOISON | \
+ VM_FAULT_HWPOISON_LARGE | VM_FAULT_FALLBACK)
+
+#define VM_FAULT_RESULT_TRACE \
+ { VM_FAULT_OOM, "OOM" }, \
+ { VM_FAULT_SIGBUS, "SIGBUS" }, \
+ { VM_FAULT_MAJOR, "MAJOR" }, \
+ { VM_FAULT_WRITE, "WRITE" }, \
+ { VM_FAULT_HWPOISON, "HWPOISON" }, \
+ { VM_FAULT_HWPOISON_LARGE, "HWPOISON_LARGE" }, \
+ { VM_FAULT_SIGSEGV, "SIGSEGV" }, \
+ { VM_FAULT_NOPAGE, "NOPAGE" }, \
+ { VM_FAULT_LOCKED, "LOCKED" }, \
+ { VM_FAULT_RETRY, "RETRY" }, \
+ { VM_FAULT_FALLBACK, "FALLBACK" }, \
+ { VM_FAULT_DONE_COW, "DONE_COW" }, \
+ { VM_FAULT_NEEDDSYNC, "NEEDDSYNC" }
+
struct vm_special_mapping {
const char *name; /* The name, e.g. "[vdso]". */

--
1.9.1



2019-01-08 18:56:02

by Matthew Wilcox

[permalink] [raw]
Subject: Re: [PATCH v4] mm: Create the new vm_fault_t type

On Wed, Jan 09, 2019 at 12:00:41AM +0530, Souptick Joarder wrote:
> Page fault handlers are supposed to return VM_FAULT codes,
> but some drivers/file systems mistakenly return error
> numbers. Now that all drivers/file systems have been converted
> to use the vm_fault_t return type, change the type definition
> to no longer be compatible with 'int'. By making it an unsigned
> int, the function prototype becomes incompatible with a function
> which returns int. Sparse will detect any attempts to return a
> value which is not a VM_FAULT code.
>
> VM_FAULT_SET_HINDEX and VM_FAULT_GET_HINDEX values are changed
> to avoid conflict with other VM_FAULT codes.
>
> Signed-off-by: Souptick Joarder <[email protected]>
> Reviewed-by: William Kucharski <[email protected]>
> Reviewed-by: Mike Rapoport <[email protected]>

Reviewed-by: Matthew Wilcox <[email protected]>

2019-01-09 11:54:17

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v4] mm: Create the new vm_fault_t type

Hi Souptick,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v5.0-rc1 next-20190109]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Souptick-Joarder/mm-Create-the-new-vm_fault_t-type/20190109-154216
config: x86_64-allmodconfig (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64

All warnings (new ones prefixed by >>):

>> arch/x86/mm/fault.c:1051:39: warning: restricted vm_fault_t degrades to integer
arch/x86/mm/fault.c:1057:29: warning: restricted vm_fault_t degrades to integer
arch/x86/mm/fault.c:1059:29: warning: restricted vm_fault_t degrades to integer
>> arch/x86/mm/fault.c:1094:62: warning: incorrect type in argument 4 (different base types)
arch/x86/mm/fault.c:1094:62: expected unsigned int fault
arch/x86/mm/fault.c:1094:62: got restricted vm_fault_t [usertype] fault

vim +1051 arch/x86/mm/fault.c

92181f190 Nick Piggin 2009-01-20 1031
2d4a71676 Ingo Molnar 2009-02-20 1032 static void
a6e04aa92 Andi Kleen 2009-09-16 1033 do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
27274f731 Eric W. Biederman 2018-09-18 1034 unsigned int fault)
92181f190 Nick Piggin 2009-01-20 1035 {
92181f190 Nick Piggin 2009-01-20 1036 struct task_struct *tsk = current;
92181f190 Nick Piggin 2009-01-20 1037
2d4a71676 Ingo Molnar 2009-02-20 1038 /* Kernel mode? Handle exceptions or die: */
1067f0309 Ricardo Neri 2017-10-27 1039 if (!(error_code & X86_PF_USER)) {
4fc349011 Andy Lutomirski 2011-11-07 1040 no_context(regs, error_code, address, SIGBUS, BUS_ADRERR);
960545691 Linus Torvalds 2010-08-13 1041 return;
960545691 Linus Torvalds 2010-08-13 1042 }
2d4a71676 Ingo Molnar 2009-02-20 1043
cd1b68f08 Ingo Molnar 2009-02-20 1044 /* User-space => ok to do another page fault: */
92181f190 Nick Piggin 2009-01-20 1045 if (is_prefetch(regs, error_code, address))
92181f190 Nick Piggin 2009-01-20 1046 return;
2d4a71676 Ingo Molnar 2009-02-20 1047
e49d3cbef Andy Lutomirski 2018-11-19 1048 set_signal_archinfo(address, error_code);
2d4a71676 Ingo Molnar 2009-02-20 1049
a6e04aa92 Andi Kleen 2009-09-16 1050 #ifdef CONFIG_MEMORY_FAILURE
f672b49b0 Andi Kleen 2010-09-27 @1051 if (fault & (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE)) {
40e553946 Eric W. Biederman 2018-01-19 1052 unsigned lsb = 0;
40e553946 Eric W. Biederman 2018-01-19 1053
40e553946 Eric W. Biederman 2018-01-19 1054 pr_err(
a6e04aa92 Andi Kleen 2009-09-16 1055 "MCE: Killing %s:%d due to hardware memory corruption fault at %lx\n",
a6e04aa92 Andi Kleen 2009-09-16 1056 tsk->comm, tsk->pid, address);
40e553946 Eric W. Biederman 2018-01-19 1057 if (fault & VM_FAULT_HWPOISON_LARGE)
40e553946 Eric W. Biederman 2018-01-19 1058 lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
40e553946 Eric W. Biederman 2018-01-19 1059 if (fault & VM_FAULT_HWPOISON)
40e553946 Eric W. Biederman 2018-01-19 1060 lsb = PAGE_SHIFT;
40e553946 Eric W. Biederman 2018-01-19 1061 force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb, tsk);
40e553946 Eric W. Biederman 2018-01-19 1062 return;
a6e04aa92 Andi Kleen 2009-09-16 1063 }
a6e04aa92 Andi Kleen 2009-09-16 1064 #endif
b4fd52f25 Eric W. Biederman 2018-09-18 1065 force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)address, tsk);
92181f190 Nick Piggin 2009-01-20 1066 }
92181f190 Nick Piggin 2009-01-20 1067
3a13c4d76 Johannes Weiner 2013-09-12 1068 static noinline void
2d4a71676 Ingo Molnar 2009-02-20 1069 mm_fault_error(struct pt_regs *regs, unsigned long error_code,
25c102d80 Eric W. Biederman 2018-09-18 1070 unsigned long address, vm_fault_t fault)
92181f190 Nick Piggin 2009-01-20 1071 {
1067f0309 Ricardo Neri 2017-10-27 1072 if (fatal_signal_pending(current) && !(error_code & X86_PF_USER)) {
4fc349011 Andy Lutomirski 2011-11-07 1073 no_context(regs, error_code, address, 0, 0);
3a13c4d76 Johannes Weiner 2013-09-12 1074 return;
b80ef10e8 KOSAKI Motohiro 2011-05-26 1075 }
b80ef10e8 KOSAKI Motohiro 2011-05-26 1076
2d4a71676 Ingo Molnar 2009-02-20 1077 if (fault & VM_FAULT_OOM) {
f86268549 Andrey Vagin 2011-03-09 1078 /* Kernel mode? Handle exceptions or die: */
1067f0309 Ricardo Neri 2017-10-27 1079 if (!(error_code & X86_PF_USER)) {
4fc349011 Andy Lutomirski 2011-11-07 1080 no_context(regs, error_code, address,
4fc349011 Andy Lutomirski 2011-11-07 1081 SIGSEGV, SEGV_MAPERR);
3a13c4d76 Johannes Weiner 2013-09-12 1082 return;
f86268549 Andrey Vagin 2011-03-09 1083 }
f86268549 Andrey Vagin 2011-03-09 1084
c2d23f919 David Rientjes 2012-12-12 1085 /*
c2d23f919 David Rientjes 2012-12-12 1086 * We ran out of memory, call the OOM killer, and return the
c2d23f919 David Rientjes 2012-12-12 1087 * userspace (which will retry the fault, or kill us if we got
c2d23f919 David Rientjes 2012-12-12 1088 * oom-killed):
c2d23f919 David Rientjes 2012-12-12 1089 */
c2d23f919 David Rientjes 2012-12-12 1090 pagefault_out_of_memory();
2d4a71676 Ingo Molnar 2009-02-20 1091 } else {
f672b49b0 Andi Kleen 2010-09-27 1092 if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
f672b49b0 Andi Kleen 2010-09-27 1093 VM_FAULT_HWPOISON_LARGE))
27274f731 Eric W. Biederman 2018-09-18 @1094 do_sigbus(regs, error_code, address, fault);
33692f275 Linus Torvalds 2015-01-29 1095 else if (fault & VM_FAULT_SIGSEGV)
768fd9c69 Eric W. Biederman 2018-09-18 1096 bad_area_nosemaphore(regs, error_code, address);
92181f190 Nick Piggin 2009-01-20 1097 else
92181f190 Nick Piggin 2009-01-20 1098 BUG();
92181f190 Nick Piggin 2009-01-20 1099 }
2d4a71676 Ingo Molnar 2009-02-20 1100 }
92181f190 Nick Piggin 2009-01-20 1101

:::::: The code at line 1051 was first introduced by commit
:::::: f672b49b07a4a152fc4251f2aec6b4d05164c4cd x86: HWPOISON: Report correct address granuality for huge hwpoison faults

:::::: TO: Andi Kleen <[email protected]>
:::::: CC: Andi Kleen <[email protected]>

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation


Attachments:
(No filename) (6.67 kB)
.config.gz (65.66 kB)
Download all attachments