aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc/mm/fault.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/parisc/mm/fault.c')
-rw-r--r--arch/parisc/mm/fault.c33
1 files changed, 29 insertions, 4 deletions
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
index 5b101f6a5607..e247edbca68e 100644
--- a/arch/parisc/mm/fault.c
+++ b/arch/parisc/mm/fault.c
@@ -17,6 +17,7 @@
17#include <linux/interrupt.h> 17#include <linux/interrupt.h>
18#include <linux/extable.h> 18#include <linux/extable.h>
19#include <linux/uaccess.h> 19#include <linux/uaccess.h>
20#include <linux/hugetlb.h>
20 21
21#include <asm/traps.h> 22#include <asm/traps.h>
22 23
@@ -261,7 +262,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
261 struct task_struct *tsk; 262 struct task_struct *tsk;
262 struct mm_struct *mm; 263 struct mm_struct *mm;
263 unsigned long acc_type; 264 unsigned long acc_type;
264 int fault; 265 int fault = 0;
265 unsigned int flags; 266 unsigned int flags;
266 267
267 if (faulthandler_disabled()) 268 if (faulthandler_disabled())
@@ -315,7 +316,8 @@ good_area:
315 goto out_of_memory; 316 goto out_of_memory;
316 else if (fault & VM_FAULT_SIGSEGV) 317 else if (fault & VM_FAULT_SIGSEGV)
317 goto bad_area; 318 goto bad_area;
318 else if (fault & VM_FAULT_SIGBUS) 319 else if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
320 VM_FAULT_HWPOISON_LARGE))
319 goto bad_area; 321 goto bad_area;
320 BUG(); 322 BUG();
321 } 323 }
@@ -352,8 +354,7 @@ bad_area:
352 354
353 if (user_mode(regs)) { 355 if (user_mode(regs)) {
354 struct siginfo si; 356 struct siginfo si;
355 357 unsigned int lsb = 0;
356 show_signal_msg(regs, code, address, tsk, vma);
357 358
358 switch (code) { 359 switch (code) {
359 case 15: /* Data TLB miss fault/Data page fault */ 360 case 15: /* Data TLB miss fault/Data page fault */
@@ -386,6 +387,30 @@ bad_area:
386 si.si_code = (code == 26) ? SEGV_ACCERR : SEGV_MAPERR; 387 si.si_code = (code == 26) ? SEGV_ACCERR : SEGV_MAPERR;
387 break; 388 break;
388 } 389 }
390
391#ifdef CONFIG_MEMORY_FAILURE
392 if (fault & (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE)) {
393 printk(KERN_ERR
394 "MCE: Killing %s:%d due to hardware memory corruption fault at %08lx\n",
395 tsk->comm, tsk->pid, address);
396 si.si_signo = SIGBUS;
397 si.si_code = BUS_MCEERR_AR;
398 }
399#endif
400
401 /*
402 * Either small page or large page may be poisoned.
403 * In other words, VM_FAULT_HWPOISON_LARGE and
404 * VM_FAULT_HWPOISON are mutually exclusive.
405 */
406 if (fault & VM_FAULT_HWPOISON_LARGE)
407 lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
408 else if (fault & VM_FAULT_HWPOISON)
409 lsb = PAGE_SHIFT;
410 else
411 show_signal_msg(regs, code, address, tsk, vma);
412 si.si_addr_lsb = lsb;
413
389 si.si_errno = 0; 414 si.si_errno = 0;
390 si.si_addr = (void __user *) address; 415 si.si_addr = (void __user *) address;
391 force_sig_info(si.si_signo, &si, current); 416 force_sig_info(si.si_signo, &si, current);