diff options
author | Anton Blanchard <anton@samba.org> | 2014-09-24 02:59:57 -0400 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2014-10-02 03:15:13 -0400 |
commit | 3913fdd7a23d9d8480ce3a6ca9cdf78bf0dec5a0 (patch) | |
tree | 9edd93074c68ffbfff5ee8800bc44ff34938cc7c /arch/powerpc/mm/fault.c | |
parent | 63af52629adcd1313c7db252f085263012ecd9db (diff) |
powerpc: Add VM_FAULT_HWPOISON handling to powerpc page fault handler
do_page_fault was missing knowledge of HWPOISON, and we would oops
if userspace tried to access a poisoned page:
kernel BUG at arch/powerpc/mm/fault.c:180!
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/mm/fault.c')
-rw-r--r-- | arch/powerpc/mm/fault.c | 17 |
1 files changed, 11 insertions, 6 deletions
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index abc8c816a326..588b6ccc0569 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
@@ -114,7 +114,8 @@ static int store_updates_sp(struct pt_regs *regs) | |||
114 | #define MM_FAULT_CONTINUE -1 | 114 | #define MM_FAULT_CONTINUE -1 |
115 | #define MM_FAULT_ERR(sig) (sig) | 115 | #define MM_FAULT_ERR(sig) (sig) |
116 | 116 | ||
117 | static int do_sigbus(struct pt_regs *regs, unsigned long address) | 117 | static int do_sigbus(struct pt_regs *regs, unsigned long address, |
118 | unsigned int fault) | ||
118 | { | 119 | { |
119 | siginfo_t info; | 120 | siginfo_t info; |
120 | 121 | ||
@@ -128,6 +129,13 @@ static int do_sigbus(struct pt_regs *regs, unsigned long address) | |||
128 | info.si_errno = 0; | 129 | info.si_errno = 0; |
129 | info.si_code = BUS_ADRERR; | 130 | info.si_code = BUS_ADRERR; |
130 | info.si_addr = (void __user *)address; | 131 | info.si_addr = (void __user *)address; |
132 | #ifdef CONFIG_MEMORY_FAILURE | ||
133 | if (fault & (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE)) { | ||
134 | pr_err("MCE: Killing %s:%d due to hardware memory corruption fault at %lx\n", | ||
135 | current->comm, current->pid, address); | ||
136 | info.si_code = BUS_MCEERR_AR; | ||
137 | } | ||
138 | #endif | ||
131 | force_sig_info(SIGBUS, &info, current); | 139 | force_sig_info(SIGBUS, &info, current); |
132 | return MM_FAULT_RETURN; | 140 | return MM_FAULT_RETURN; |
133 | } | 141 | } |
@@ -170,11 +178,8 @@ static int mm_fault_error(struct pt_regs *regs, unsigned long addr, int fault) | |||
170 | return MM_FAULT_RETURN; | 178 | return MM_FAULT_RETURN; |
171 | } | 179 | } |
172 | 180 | ||
173 | /* Bus error. x86 handles HWPOISON here, we'll add this if/when | 181 | if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE)) |
174 | * we support the feature in HW | 182 | return do_sigbus(regs, addr, fault); |
175 | */ | ||
176 | if (fault & VM_FAULT_SIGBUS) | ||
177 | return do_sigbus(regs, addr); | ||
178 | 183 | ||
179 | /* We don't understand the fault code, this is fatal */ | 184 | /* We don't understand the fault code, this is fatal */ |
180 | BUG(); | 185 | BUG(); |