diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2017-07-19 14:49:31 +1000 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2017-08-03 16:06:45 +1000 |
commit | f3d96e698ed0f83d8faa35071ea9ca0a57e74c50 (patch) | |
tree | 6597a1cf1224d3aa81eefd1b3a507e1b9bb317f5 /arch/powerpc/mm/fault.c | |
parent | e6c8290a894bcaf0d8f06c504a04da3412a3cf55 (diff) | |
download | linux-f3d96e698ed0f83d8faa35071ea9ca0a57e74c50.tar.gz linux-f3d96e698ed0f83d8faa35071ea9ca0a57e74c50.tar.bz2 linux-f3d96e698ed0f83d8faa35071ea9ca0a57e74c50.zip |
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>
Diffstat (limited to 'arch/powerpc/mm/fault.c')
-rw-r--r-- | arch/powerpc/mm/fault.c | 32 |
1 files changed, 14 insertions, 18 deletions
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index e2f3144a48b9..4470500b4871 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -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 |