summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm/fault.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2017-07-19 14:49:31 +1000
committerMichael Ellerman <mpe@ellerman.id.au>2017-08-03 16:06:45 +1000
commitf3d96e698ed0f83d8faa35071ea9ca0a57e74c50 (patch)
tree6597a1cf1224d3aa81eefd1b3a507e1b9bb317f5 /arch/powerpc/mm/fault.c
parente6c8290a894bcaf0d8f06c504a04da3412a3cf55 (diff)
downloadlinux-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.c32
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