Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 606f95e4 authored by Helge Deller's avatar Helge Deller
Browse files

parisc: Add HWPOISON page fault handler code



Commit 24587380 ("parisc: Add MADV_HWPOISON and MADV_SOFT_OFFLINE") added
the necessary constants to handle hardware-poisoning. Those were needed to
support the page deallocation feature from firmware.

But I completely missed to add the relevant fault handler code. This now
showed up when I ran the madvise07 testcase from the Linux Test Project,
which failed with a kernel BUG at arch/parisc/mm/fault.c:320.

With this patch the parisc kernel now behaves like other platforms and
gives the same kernel syslog warnings when poisoning pages.

Signed-off-by: default avatarHelge Deller <deller@gmx.de>
parent a7e6601f
Loading
Loading
Loading
Loading
+29 −4
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/interrupt.h>
#include <linux/extable.h>
#include <linux/uaccess.h>
#include <linux/hugetlb.h>

#include <asm/traps.h>

@@ -261,7 +262,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
	struct task_struct *tsk;
	struct mm_struct *mm;
	unsigned long acc_type;
	int fault;
	int fault = 0;
	unsigned int flags;

	if (faulthandler_disabled())
@@ -315,7 +316,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
			goto out_of_memory;
		else if (fault & VM_FAULT_SIGSEGV)
			goto bad_area;
		else if (fault & VM_FAULT_SIGBUS)
		else if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
				  VM_FAULT_HWPOISON_LARGE))
			goto bad_area;
		BUG();
	}
@@ -352,8 +354,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,

	if (user_mode(regs)) {
		struct siginfo si;

		show_signal_msg(regs, code, address, tsk, vma);
		unsigned int lsb = 0;

		switch (code) {
		case 15:	/* Data TLB miss fault/Data page fault */
@@ -386,6 +387,30 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
			si.si_code = (code == 26) ? SEGV_ACCERR : SEGV_MAPERR;
			break;
		}

#ifdef CONFIG_MEMORY_FAILURE
		if (fault & (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE)) {
			printk(KERN_ERR
	"MCE: Killing %s:%d due to hardware memory corruption fault at %08lx\n",
			tsk->comm, tsk->pid, address);
			si.si_signo = SIGBUS;
			si.si_code = BUS_MCEERR_AR;
		}
#endif

		/*
		 * Either small page or large page may be poisoned.
		 * In other words, VM_FAULT_HWPOISON_LARGE and
		 * VM_FAULT_HWPOISON are mutually exclusive.
		 */
		if (fault & VM_FAULT_HWPOISON_LARGE)
			lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
		else if (fault & VM_FAULT_HWPOISON)
			lsb = PAGE_SHIFT;
		else
			show_signal_msg(regs, code, address, tsk, vma);
		si.si_addr_lsb = lsb;

		si.si_errno = 0;
		si.si_addr = (void __user *) address;
		force_sig_info(si.si_signo, &si, current);