From: opendmb@gmail.com (Doug Berger)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 3/9] arm64: mm: install SError abort handler
Date: Fri, 24 Mar 2017 07:46:26 -0700 [thread overview]
Message-ID: <20170324144632.5896-4-opendmb@gmail.com> (raw)
In-Reply-To: <20170324144632.5896-1-opendmb@gmail.com>
This commit adds support for minimal handling of SError aborts and
allows them to be hooked by a driver or other part of the kernel to
install a custom SError abort handler. The hook function returns
the previously registered handler so that handlers may be chained if
desired.
The handler should return the value 0 if the error has been handled,
otherwise the handler should either call the next handler in the
chain or return a non-zero value.
Since the Instruction Specific Syndrome value for SError aborts is
implementation specific the registerred handlers must implement
their own parsing of the syndrome.
Signed-off-by: Doug Berger <opendmb@gmail.com>
---
arch/arm64/include/asm/system_misc.h | 2 ++
arch/arm64/kernel/entry.S | 69 ++++++++++++++++++++++++++++++++----
arch/arm64/mm/fault.c | 31 ++++++++++++++++
3 files changed, 95 insertions(+), 7 deletions(-)
diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h
index e05f5b8c7c1c..60ac784ff4e6 100644
--- a/arch/arm64/include/asm/system_misc.h
+++ b/arch/arm64/include/asm/system_misc.h
@@ -41,6 +41,8 @@ void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
struct pt_regs *),
int sig, int code, const char *name);
+void *hook_serror_handler(int (*fn)(unsigned long, unsigned int,
+ struct pt_regs *));
struct mm_struct;
extern void show_pte(struct mm_struct *mm, unsigned long addr);
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 43512d4d7df2..d043d66b390d 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -323,18 +323,18 @@ ENTRY(vectors)
ventry el1_sync // Synchronous EL1h
ventry el1_irq // IRQ EL1h
ventry el1_fiq_invalid // FIQ EL1h
- ventry el1_error_invalid // Error EL1h
+ ventry el1_error // Error EL1h
ventry el0_sync // Synchronous 64-bit EL0
ventry el0_irq // IRQ 64-bit EL0
ventry el0_fiq_invalid // FIQ 64-bit EL0
- ventry el0_error_invalid // Error 64-bit EL0
+ ventry el0_error // Error 64-bit EL0
#ifdef CONFIG_COMPAT
ventry el0_sync_compat // Synchronous 32-bit EL0
ventry el0_irq_compat // IRQ 32-bit EL0
ventry el0_fiq_invalid_compat // FIQ 32-bit EL0
- ventry el0_error_invalid_compat // Error 32-bit EL0
+ ventry el0_error_compat // Error 32-bit EL0
#else
ventry el0_sync_invalid // Synchronous 32-bit EL0
ventry el0_irq_invalid // IRQ 32-bit EL0
@@ -374,10 +374,6 @@ ENDPROC(el0_error_invalid)
el0_fiq_invalid_compat:
inv_entry 0, BAD_FIQ, 32
ENDPROC(el0_fiq_invalid_compat)
-
-el0_error_invalid_compat:
- inv_entry 0, BAD_ERROR, 32
-ENDPROC(el0_error_invalid_compat)
#endif
el1_sync_invalid:
@@ -508,6 +504,34 @@ el1_preempt:
ret x24
#endif
+ .align 6
+el1_error:
+ kernel_entry 1
+ mrs x1, esr_el1 // read the syndrome register
+ lsr x24, x1, #ESR_ELx_EC_SHIFT // exception class
+ cmp x24, #ESR_ELx_EC_SERROR // SError exception in EL1
+ b.ne el1_error_inv
+el1_serr:
+ mrs x0, far_el1
+ enable_dbg
+ // re-enable interrupts if they were enabled in the aborted context
+ tbnz x23, #7, 1f // PSR_I_BIT
+ enable_irq
+1:
+ mov x2, sp // struct pt_regs
+ bl do_serr_abort
+
+ // disable interrupts before pulling preserved data off the stack
+ disable_irq
+ kernel_exit 1
+el1_error_inv:
+ enable_dbg
+ mov x0, sp
+ mov x2, x1
+ mov x1, #BAD_ERROR
+ b bad_mode
+ENDPROC(el1_error)
+
/*
* EL0 mode handlers.
*/
@@ -584,6 +608,11 @@ el0_svc_compat:
el0_irq_compat:
kernel_entry 0, 32
b el0_irq_naked
+
+ .align 6
+el0_error_compat:
+ kernel_entry 0, 32
+ b el0_error_naked
#endif
el0_da:
@@ -705,6 +734,32 @@ el0_irq_naked:
b ret_to_user
ENDPROC(el0_irq)
+ .align 6
+el0_error:
+ kernel_entry 0
+el0_error_naked:
+ mrs x25, esr_el1 // read the syndrome register
+ lsr x24, x25, #ESR_ELx_EC_SHIFT // exception class
+ cmp x24, #ESR_ELx_EC_SERROR // SError exception in EL0
+ b.ne el0_error_inv
+el0_serr:
+ mrs x26, far_el1
+ // enable interrupts before calling the main handler
+ enable_dbg_and_irq
+ ct_user_exit
+ bic x0, x26, #(0xff << 56)
+ mov x1, x25
+ mov x2, sp
+ bl do_serr_abort
+ b ret_to_user
+el0_error_inv:
+ enable_dbg
+ mov x0, sp
+ mov x1, #BAD_ERROR
+ mov x2, x25
+ b bad_mode
+ENDPROC(el0_error)
+
/*
* Register switch for AArch64. The callee-saved registers need to be saved
* and restored. On entry:
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 43319ed58a47..577fecea7c7d 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -705,3 +705,34 @@ int cpu_enable_pan(void *__unused)
return 0;
}
#endif /* CONFIG_ARM64_PAN */
+
+static int (*serror_handler)(unsigned long, unsigned int,
+ struct pt_regs *) __ro_after_init;
+
+void *__init hook_serror_handler(int (*fn)(unsigned long, unsigned int,
+ struct pt_regs *))
+{
+ void *ret = serror_handler;
+
+ serror_handler = fn;
+ return ret;
+}
+
+asmlinkage void __exception do_serr_abort(unsigned long addr, unsigned int esr,
+ struct pt_regs *regs)
+{
+ struct siginfo info;
+
+ if (serror_handler)
+ if (!serror_handler(addr, esr, regs))
+ return;
+
+ pr_alert("Unhandled SError: (0x%08x)@0x%016lx\n", esr, addr);
+ __show_regs(regs);
+
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = ILL_ILLOPC;
+ info.si_addr = (void __user *)addr;
+ arm64_notify_die("", regs, &info, esr);
+}
--
2.12.0
next prev parent reply other threads:[~2017-03-24 14:46 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-03-24 14:46 [PATCH 0/9] bus: brcmstb_gisb: add support for GISBv7 arbiter Doug Berger
2017-03-24 14:46 ` [PATCH 1/9] arm64: mm: Allow installation of memory abort handlers Doug Berger
2017-03-24 14:46 ` [PATCH 2/9] arm64: mm: mark fault_info __ro_after_init Doug Berger
2017-03-24 14:46 ` Doug Berger [this message]
2017-03-24 15:16 ` [PATCH 3/9] arm64: mm: install SError abort handler Mark Rutland
2017-03-24 16:48 ` Doug Berger
2017-03-24 17:35 ` Mark Rutland
2017-03-24 17:53 ` Florian Fainelli
2017-03-24 18:31 ` Mark Rutland
2017-03-24 19:02 ` Florian Fainelli
2017-03-25 10:06 ` Marc Zyngier
2017-03-27 20:19 ` Florian Fainelli
2017-03-24 14:46 ` [PATCH 4/9] bus: brcmstb_gisb: Use register offsets with writes too Doug Berger
2017-03-25 5:21 ` Gregory Fong
2017-03-24 14:46 ` [PATCH 5/9] bus: brcmstb_gisb: Correct hooking of ARM aborts Doug Berger
2017-03-24 14:46 ` [PATCH 6/9] bus: brcmstb_gisb: correct support for 64-bit address output Doug Berger
2017-03-25 5:36 ` Gregory Fong
2017-03-24 14:46 ` [PATCH 7/9] bus: brcmstb_gisb: Add ARM64 support Doug Berger
2017-03-24 14:46 ` [PATCH 8/9] bus: brcmstb_gisb: add ARM64 SError support Doug Berger
2017-03-24 14:46 ` [PATCH 9/9] bus: brcmstb_gisb: update to support new revision Doug Berger
2017-03-24 15:03 ` [PATCH 0/9] bus: brcmstb_gisb: add support for GISBv7 arbiter Mark Rutland
2017-03-24 16:02 ` Doug Berger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170324144632.5896-4-opendmb@gmail.com \
--to=opendmb@gmail.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).