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: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
e6c8290a89
commit
f3d96e698e
1 changed files with 14 additions and 18 deletions
|
@ -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))
|
#if (defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
|
||||||
#define page_fault_is_write(__err) ((__err) & ESR_DST)
|
#define page_fault_is_write(__err) ((__err) & ESR_DST)
|
||||||
|
#define page_fault_is_bad(__err) (0)
|
||||||
#else
|
#else
|
||||||
#define page_fault_is_write(__err) ((__err) & DSISR_ISSTORE)
|
#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
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -237,25 +245,13 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
|
||||||
if (unlikely(debugger_fault_handler(regs)))
|
if (unlikely(debugger_fault_handler(regs)))
|
||||||
goto bail;
|
goto bail;
|
||||||
|
|
||||||
#if defined(CONFIG_6xx)
|
if (unlikely(page_fault_is_bad(error_code))) {
|
||||||
if (error_code & 0x95700000) {
|
if (is_user)
|
||||||
/* an error such as lwarx to I/O controller space,
|
_exception(SIGBUS, regs, BUS_OBJERR, address);
|
||||||
address matching DABR, eciwx, etc. */
|
else
|
||||||
code = SEGV_ACCERR;
|
rc = SIGBUS;
|
||||||
goto bad_area_nosemaphore;
|
goto bail;
|
||||||
}
|
}
|
||||||
#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;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_8xx */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The kernel should never take an execute fault nor should it
|
* The kernel should never take an execute fault nor should it
|
||||||
|
|
Loading…
Add table
Reference in a new issue