From: John Jacques <john.jacq...@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.jacq...@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.jacq...@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.jacq...@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

-- 
_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to