ARM64: Need to ignore exception in bad_mode()
Hari Vyas
hari.vyas at broadcom.com
Wed Dec 6 22:59:24 PST 2017
(Re-sending mail in plain text format)
Hi Will , Catalin,
One of our Broadcom SoC "Stingray" is based on ARM64 architecture.
In pcie hot-plug-out scenario where EP card is surprisingly plugged-out,
few ongoing memory transaction times out and our pcie IDM wrapper
eventually results in an exception which is expected one in
this case.
If we don't ignore exception in this case, kernel crashes.
We are planning to ignore "expected exception" by changing entry.S
and traps.c. Please check and provide us your opinion regarding below
approach. I have highlighted important changes of
arch/arm64/kernel/entry.S and arch/arm64/kernel/traps.c
hariv at vijay-Precision-WorkStation-T3400:~/BCM_MASTER/kernel$ git diff
arch/arm64/kernel/entry.S
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index e1c59d4..54b5eb2 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -430,6 +430,9 @@ __bad_stack:
mov x1, #\reason
mrs x2, esr_el1
bl bad_mode
+ cbnz x0, 2f
+ kernel_exit el
+2:
ASM_BUG()
.endm
hariv at vijay-Precision-WorkStation-T3400:~/BCM_MASTER/kernel$ git diff
arch/arm64/kernel/traps.c
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 8383af1..709f399 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -48,6 +48,8 @@
#include <asm/exception.h>
#include <asm/system_misc.h>
#include <asm/sysreg.h>
int show_unhandled_signals = 1;
+struct exception_list {
+ struct list_head head;
+ long unsigned data;
+ int (*cb)(long unsigned data);
+};
+struct list_head exception_head = LIST_HEAD_INIT(exception_head);
+
+int register_exception(int (*cb)(long unsigned data), long unsigned data)
+{
+ struct exception_list *entry;
+
+ entry=kmalloc(sizeof(struct exception_list *),GFP_KERNEL);
+ entry->data = data;
+ entry->cb = cb;
+ list_add(&entry->head,&exception_head);
+ return 0;
+}
+EXPORT_SYMBOL(register_exception);
+
/*
* Dump out the contents of some kernel memory nicely...
*/
+
static void dump_mem(const char *lvl, const char *str, unsigned long
bottom,
unsigned long top)
{
@@ -633,10 +655,22 @@ const char *esr_get_class_string(u32 esr)
* bad_mode handles the impossible case in the exception vector. This is
always
* fatal.
*/
-asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int
esr)
+asmlinkage int bad_mode(struct pt_regs *regs, int reason, unsigned int
esr)
{
+ struct exception_list *entry;
+ struct list_head *ptr;
+ int ret;
+
console_verbose();
+ list_for_each(ptr,&exception_head) {
+ entry=list_entry(ptr,struct exception_list,head);
+ ret = entry->cb(entry->data);
+ if (ret == NOTIFY_STOP) {
+ pr_crit("Expected exception so ignoring\n");
+ return 0;
+ }
+ }
pr_crit("Bad mode in %s handler detected on CPU%d, code 0x%08x --
%s\n",
handler[reason], smp_processor_id(), esr,
esr_get_class_string(esr));
@@ -644,6 +678,7 @@ asmlinkage void bad_mode(struct pt_regs *regs, int
reason, u
die("Oops - bad mode", regs, 0);
local_irq_disable();
panic("bad mode");
+ return 1; /* Must not reach */
}
/*
hariv at vijay-Precision-WorkStation-T3400:~/BCM_MASTER/kernel$
Regards,
hari
More information about the linux-arm-kernel
mailing list