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

Commit f3d96e69 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Michael Ellerman
Browse files

powerpc/mm: Overhaul handling of bad page faults



A bad page fault is when the HW signals an error such as a bad
copy/paste, an AMO error, or some other type of error that will
not be fixed by updating the PTE.

Use a helper page_fault_is_bad() to check for bad page faults thus
removing the per-processor family open-coding in __do_page_fault()
and trigger a SIGBUS rather than a SIGSEGV which is more appropriate.

Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent e6c8290a
Loading
Loading
Loading
Loading
+14 −18
Original line number Diff line number Diff line
@@ -188,8 +188,16 @@ static int mm_fault_error(struct pt_regs *regs, unsigned long addr, int fault)
 */
#if (defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
#define page_fault_is_write(__err)	((__err) & ESR_DST)
#define page_fault_is_bad(__err)	(0)
#else
#define page_fault_is_write(__err)	((__err) & DSISR_ISSTORE)
#if defined(CONFIG_8xx)
#define page_fault_is_bad(__err)	((__err) & 0x10000000)
#elif defined(CONFIG_PPC64)
#define page_fault_is_bad(__err)	((__err) & DSISR_BAD_FAULT_64S)
#else
#define page_fault_is_bad(__err)	((__err) & DSISR_BAD_FAULT_32S)
#endif
#endif

/*
@@ -237,25 +245,13 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
	if (unlikely(debugger_fault_handler(regs)))
		goto bail;

#if defined(CONFIG_6xx)
	if (error_code & 0x95700000) {
		/* an error such as lwarx to I/O controller space,
		   address matching DABR, eciwx, etc. */
		code = SEGV_ACCERR;
		goto bad_area_nosemaphore;
	}
#endif /* CONFIG_6xx */
#if defined(CONFIG_8xx)
        /* The MPC8xx seems to always set 0x80000000, which is
         * "undefined".  Of those that can be set, this is the only
         * one which seems bad.
         */
	if (error_code & 0x10000000) {
                /* Guarded storage error. */
		code = SEGV_ACCERR;
		goto bad_area_nosemaphore;
	if (unlikely(page_fault_is_bad(error_code))) {
		if (is_user)
			_exception(SIGBUS, regs, BUS_OBJERR, address);
		else
			rc = SIGBUS;
		goto bail;
	}
#endif /* CONFIG_8xx */

	/*
	 * The kernel should never take an execute fault nor should it