[linux-yocto] [PATCH 15/15] drivers/misc: Add Fault Handling for Axxia

Daniel Dragomir daniel.dragomir at windriver.com
Tue Jun 27 08:41:15 PDT 2017


From: John Jacques <john.jacques at intel.com>

Add system error handlers for Axxia parts.

This is intended to handle SErrors (Asynchronous Aborts) caused by
sRIO optional register accesses, which are not supported by the
Axxia sRIO hardware.  As it isn't possible to determine the cause
completely, a mechanism is provided to enable or disable masking
from user space.

Signed-off-by: John Jacques <john.jacques at intel.com>
---
 arch/arm/mach-axxia/Makefile |   2 +-
 arch/arm/mach-axxia/axxia.c  |   4 -
 arch/arm64/kernel/entry.S    |  48 ++++++++++++
 drivers/misc/Kconfig         |   6 ++
 drivers/misc/Makefile        |   1 +
 drivers/misc/axxia-fault.c   | 177 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/axxia-fault.h  |  23 ++++++
 7 files changed, 256 insertions(+), 5 deletions(-)
 create mode 100644 drivers/misc/axxia-fault.c
 create mode 100644 include/linux/axxia-fault.h

diff --git a/arch/arm/mach-axxia/Makefile b/arch/arm/mach-axxia/Makefile
index 2ecc468..cae1d41 100644
--- a/arch/arm/mach-axxia/Makefile
+++ b/arch/arm/mach-axxia/Makefile
@@ -11,5 +11,5 @@ obj-y					+= ddr_retention.o ddr_shutdown.o
 obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
 obj-$(CONFIG_ARCH_AXXIA_GIC)		+= axxia-gic.o
 obj-$(CONFIG_HOTPLUG_CPU)		+= hotplug.o lsi_power_management.o
-obj-$(CONFIG_AXXIA_RIO)                 += rapidio.o
+#obj-$(CONFIG_AXXIA_RIO)                 += rapidio.o
 obj-$(CONFIG_HW_PERF_EVENTS)            += perf_event_platform.o smon.o
diff --git a/arch/arm/mach-axxia/axxia.c b/arch/arm/mach-axxia/axxia.c
index e1a77db..ffc01d6 100644
--- a/arch/arm/mach-axxia/axxia.c
+++ b/arch/arm/mach-axxia/axxia.c
@@ -219,10 +219,6 @@ void __init axxia_dt_init(void)
 
 	axxia_ddr_retention_init();
 
-#ifdef CONFIG_AXXIA_RIO
-	axxia_rapidio_init();
-#endif
-
 	platform_device_register(&pmu_device);
 }
 
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index bc7bece..bb69506 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -266,7 +266,23 @@ el0_fiq_invalid:
 ENDPROC(el0_fiq_invalid)
 
 el0_error_invalid:
+#ifdef CONFIG_AXXIA_FAULT
+	kernel_entry	0
+	mov		x0, sp
+	mov		x1, #0
+	mrs		x2, esr_el1
+	bl		axxia_x9xlf_fault
+	cmp		x0, #0
+	beq		1f
+	mov		x0, sp	// Return Failure
+	mov		x1, #BAD_ERROR
+	mrs		x2, esr_el1
+	b		bad_mode
+1:
+	kernel_exit	0	// Return Success
+#else
 	inv_entry 0, BAD_ERROR
+#endif
 ENDPROC(el0_error_invalid)
 
 #ifdef CONFIG_COMPAT
@@ -275,7 +291,23 @@ el0_fiq_invalid_compat:
 ENDPROC(el0_fiq_invalid_compat)
 
 el0_error_invalid_compat:
+#ifdef CONFIG_AXXIA_FAULT
+	kernel_entry	0, 32
+	mov		x0, sp
+	mov		x1, #0
+	mrs		x2, esr_el1
+	bl		axxia_x9xlf_fault
+	cmp		x0, #0
+	beq		1f
+	mov		x0, sp	// Return Failure
+	mov		x1, #BAD_ERROR
+	mrs		x2, esr_el1
+	b		bad_mode
+1:
+	kernel_exit	0	// Return Success
+#else
 	inv_entry 0, BAD_ERROR, 32
+#endif
 ENDPROC(el0_error_invalid_compat)
 #endif
 
@@ -292,7 +324,23 @@ el1_fiq_invalid:
 ENDPROC(el1_fiq_invalid)
 
 el1_error_invalid:
+#ifdef CONFIG_AXXIA_FAULT
+	kernel_entry	1
+	mov		x0, sp
+	mov		x1, #1
+	mrs		x2, esr_el1
+	bl		axxia_x9xlf_fault
+	cmp		x0, #0
+	beq		1f
+	mov		x0, sp	// Return Failure
+	mov		x1, #BAD_ERROR
+	mrs		x2, esr_el1
+	b		bad_mode
+1:
+	kernel_exit	1
+#else
 	inv_entry 1, BAD_ERROR
+#endif
 ENDPROC(el1_error_invalid)
 
 /*
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 1543d57..e7a3dbc 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -580,6 +580,12 @@ config AXXIA_OEM
        help
 	 OEM calls to the secure monitor for Axxia.
 
+config AXXIA_FAULT
+       bool "Axxia Fault Handlers"
+       depends on ARCH_AXXIA
+       help
+	 Add fault handlers for system aborts.
+
 config AXXIA_PEI
        bool "Axxia PEI Controller Setup"
        depends on ARCH_AXXIA
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 05e20e6..98ab9f0 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_LSI_NCR)           += lsi-ncr.o
 obj-$(CONFIG_LSI_MTC)		+= lsi-mtc.o
 obj-$(CONFIG_LSI_SMMON)         += lsi-smmon.o
 obj-$(CONFIG_AXXIA_OEM)         += axxia-oem.o
+obj-$(CONFIG_AXXIA_FAULT)       += axxia-fault.o
 obj-$(CONFIG_AXXIA_PEI)         += axxia-pei.o
 obj-$(CONFIG_AXXIA_MDIO)        += axxia-mdio.o
 obj-$(CONFIG_ECHO)		+= echo/
diff --git a/drivers/misc/axxia-fault.c b/drivers/misc/axxia-fault.c
new file mode 100644
index 0000000..e9ab5da
--- /dev/null
+++ b/drivers/misc/axxia-fault.c
@@ -0,0 +1,177 @@
+/*
+ *  Copyright (C) 2016 Intel Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ */
+
+/*
+  ==============================================================================
+  ==============================================================================
+  Private
+  ==============================================================================
+  ==============================================================================
+*/
+
+#define DEBUG
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/signal.h>
+
+#include <asm/system_misc.h>
+
+static int mask_aborts;
+module_param(mask_aborts, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+MODULE_PARM_DESC(mask_aborts, "Masking Aborts");
+
+/*
+  ------------------------------------------------------------------------------
+  axxia_x7_fault
+*/
+
+#if defined(ARM)
+
+static int
+axxia_x7_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+	if (0 == mask_aborts)
+		return -1;
+
+	pr_warn("Masking System Error...\n");
+
+	return 0;
+}
+
+#endif	/* defined(ARM) */
+
+/*
+  ------------------------------------------------------------------------------
+  axxia_x9xlf_fault
+
+  Return 0 to indicate the error is not a problem (should be ignored)
+  or non-zero to indicate that it was not handled.
+
+  This is intended to handle SErrors (Asynchronous Aborts) caused by
+  sRIO optional register accesses, which are not supported by the
+  Axxia sRIO hardware.  As it isn't possible to determine the cause
+  completely, a mechanism is provided to enable or disable masking
+  from user space.
+
+  For 5600 (Cortex-A57)
+
+      In the ESR (see ARM documentation for fields), the following
+      should be true.
+
+	    esr[31:26] = 0x2f
+	    esr[24] = 1       (iss is valid)
+	    esr[23:0] = 0x2   (slave error)
+*/
+
+asmlinkage int
+axxia_x9xlf_fault(struct pt_regs *regs, int el, unsigned long esr)
+{
+	unsigned int ec;
+	unsigned int il;
+	unsigned int iss_valid;
+	unsigned int iss_value;
+
+	pr_warn("Axxia System Error Handler\n");
+	ec = ((esr >> 26) & 0x3f);
+	il = ((esr >> 25) & 1);
+	iss_valid = ((esr & (1 << 24)) == 0) ? 0 : 1;
+	iss_value = (esr & 0xffffff);
+	pr_warn("el=%d esr=0x%lx (ec=0x%x il=%d)\n", (int)el, esr, ec, il);
+
+	if (0 == iss_valid) {
+		pr_warn("iss=INVALID\n");
+
+		return -1;
+	}
+
+	pr_warn("iss=0x%x\n", iss_value);
+
+	if ((0x2f != ec) || (2 != iss_value))
+		return -1;
+
+	if (0 == mask_aborts)
+		return -1;
+
+	pr_warn("Masking System Error...\n");
+
+	return 0;
+}
+
+/*
+  ==============================================================================
+  ==============================================================================
+  Public
+  ==============================================================================
+  ==============================================================================
+*/
+
+/*
+  ------------------------------------------------------------------------------
+  axxia_fault_get_mask
+*/
+
+int
+axxia_fault_get_mask(void)
+{
+	return mask_aborts;
+}
+
+
+/*
+  ------------------------------------------------------------------------------
+  axxia_fault_set_mask
+*/
+
+void
+axxia_fault_set_mask(int new_mask)
+{
+	mask_aborts = new_mask;
+
+	return;
+}
+
+
+/*
+  ------------------------------------------------------------------------------
+  axxia_fault_init
+*/
+
+static int __init
+axxia_fault_init(void)
+{
+#if defined(ARM)
+	if (of_find_compatible_node(NULL, NULL, "lsi,axm5500") ||
+	    of_find_compatible_node(NULL, NULL, "lsi,axm5516")) {
+		hook_fault_code(0x11, axxia_x7_fault, SIGBUS, 0,
+				"asynchronous external abort");
+		pr_debug("Set up fault handler for Axxia 5500\n");
+	}
+#elif defined(ARM64)
+	if (of_find_compatible_node(NULL, NULL, "lsi,axm5616") ||
+	    of_find_compatible_node(NULL, NULL, "lsi,axc6732"))
+		pr_debug("Set up fault handler for Axxia 5600/6700\n");
+#endif
+
+	return 0;
+}
+
+early_initcall(axxia_fault_init);
+
+MODULE_AUTHOR("John Jacques <john.jacques at intel.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Axxia Fault Handlers");
diff --git a/include/linux/axxia-fault.h b/include/linux/axxia-fault.h
new file mode 100644
index 0000000..d81c250
--- /dev/null
+++ b/include/linux/axxia-fault.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2017 Intel <john.jacques at intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __DRIVERS_MISC_AXXIA_FAULT_H
+#define __DRIVERS_MISC_AXXIA_FAULT_H
+
+asmlinkage int axxia_x9xlf_fault(struct pt_regs *, int, unsigned long);
+
+int axxia_fault_get_mask(void);
+void axxia_fault_set_mask(int);
+
+#endif /* __DRIVERS_MISC_AXXIA_FAULT_H */
-- 
2.7.4



More information about the linux-yocto mailing list