]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.5.1/x86-mce-fix-siginfo_t-si_addr-value-for-non-recoverable-memory-faults.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.5.1 / x86-mce-fix-siginfo_t-si_addr-value-for-non-recoverable-memory-faults.patch
1 From 6751ed65dc6642af64f7b8a440a75563c8aab7ae Mon Sep 17 00:00:00 2001
2 From: Tony Luck <tony.luck@intel.com>
3 Date: Wed, 11 Jul 2012 10:20:47 -0700
4 Subject: x86/mce: Fix siginfo_t->si_addr value for non-recoverable memory faults
5
6 From: Tony Luck <tony.luck@intel.com>
7
8 commit 6751ed65dc6642af64f7b8a440a75563c8aab7ae upstream.
9
10 In commit dad1743e5993f1 ("x86/mce: Only restart instruction after machine
11 check recovery if it is safe") we fixed mce_notify_process() to force a
12 signal to the current process if it was not restartable (RIPV bit not
13 set in MCG_STATUS). But doing it here means that the process doesn't
14 get told the virtual address of the fault via siginfo_t->si_addr. This
15 would prevent application level recovery from the fault.
16
17 Make a new MF_MUST_KILL flag bit for memory_failure() et al. to use so
18 that we will provide the right information with the signal.
19
20 Signed-off-by: Tony Luck <tony.luck@intel.com>
21 Acked-by: Borislav Petkov <borislav.petkov@amd.com>
22 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
23
24 ---
25 arch/x86/kernel/cpu/mcheck/mce.c | 6 ++++--
26 include/linux/mm.h | 1 +
27 mm/memory-failure.c | 14 ++++++++------
28 3 files changed, 13 insertions(+), 8 deletions(-)
29
30 --- a/arch/x86/kernel/cpu/mcheck/mce.c
31 +++ b/arch/x86/kernel/cpu/mcheck/mce.c
32 @@ -1186,6 +1186,7 @@ void mce_notify_process(void)
33 {
34 unsigned long pfn;
35 struct mce_info *mi = mce_find_info();
36 + int flags = MF_ACTION_REQUIRED;
37
38 if (!mi)
39 mce_panic("Lost physical address for unconsumed uncorrectable error", NULL, NULL);
40 @@ -1200,8 +1201,9 @@ void mce_notify_process(void)
41 * doomed. We still need to mark the page as poisoned and alert any
42 * other users of the page.
43 */
44 - if (memory_failure(pfn, MCE_VECTOR, MF_ACTION_REQUIRED) < 0 ||
45 - mi->restartable == 0) {
46 + if (!mi->restartable)
47 + flags |= MF_MUST_KILL;
48 + if (memory_failure(pfn, MCE_VECTOR, flags) < 0) {
49 pr_err("Memory error not recovered");
50 force_sig(SIGBUS, current);
51 }
52 --- a/include/linux/mm.h
53 +++ b/include/linux/mm.h
54 @@ -1591,6 +1591,7 @@ void vmemmap_populate_print_last(void);
55 enum mf_flags {
56 MF_COUNT_INCREASED = 1 << 0,
57 MF_ACTION_REQUIRED = 1 << 1,
58 + MF_MUST_KILL = 1 << 2,
59 };
60 extern int memory_failure(unsigned long pfn, int trapno, int flags);
61 extern void memory_failure_queue(unsigned long pfn, int trapno, int flags);
62 --- a/mm/memory-failure.c
63 +++ b/mm/memory-failure.c
64 @@ -345,14 +345,14 @@ static void add_to_kill(struct task_stru
65 * Also when FAIL is set do a force kill because something went
66 * wrong earlier.
67 */
68 -static void kill_procs(struct list_head *to_kill, int doit, int trapno,
69 +static void kill_procs(struct list_head *to_kill, int forcekill, int trapno,
70 int fail, struct page *page, unsigned long pfn,
71 int flags)
72 {
73 struct to_kill *tk, *next;
74
75 list_for_each_entry_safe (tk, next, to_kill, nd) {
76 - if (doit) {
77 + if (forcekill) {
78 /*
79 * In case something went wrong with munmapping
80 * make sure the process doesn't catch the
81 @@ -858,7 +858,7 @@ static int hwpoison_user_mappings(struct
82 struct address_space *mapping;
83 LIST_HEAD(tokill);
84 int ret;
85 - int kill = 1;
86 + int kill = 1, forcekill;
87 struct page *hpage = compound_head(p);
88 struct page *ppage;
89
90 @@ -888,7 +888,7 @@ static int hwpoison_user_mappings(struct
91 * be called inside page lock (it's recommended but not enforced).
92 */
93 mapping = page_mapping(hpage);
94 - if (!PageDirty(hpage) && mapping &&
95 + if (!(flags & MF_MUST_KILL) && !PageDirty(hpage) && mapping &&
96 mapping_cap_writeback_dirty(mapping)) {
97 if (page_mkclean(hpage)) {
98 SetPageDirty(hpage);
99 @@ -965,12 +965,14 @@ static int hwpoison_user_mappings(struct
100 * Now that the dirty bit has been propagated to the
101 * struct page and all unmaps done we can decide if
102 * killing is needed or not. Only kill when the page
103 - * was dirty, otherwise the tokill list is merely
104 + * was dirty or the process is not restartable,
105 + * otherwise the tokill list is merely
106 * freed. When there was a problem unmapping earlier
107 * use a more force-full uncatchable kill to prevent
108 * any accesses to the poisoned memory.
109 */
110 - kill_procs(&tokill, !!PageDirty(ppage), trapno,
111 + forcekill = PageDirty(ppage) || (flags & MF_MUST_KILL);
112 + kill_procs(&tokill, forcekill, trapno,
113 ret != SWAP_SUCCESS, p, pfn, flags);
114
115 return ret;