summaryrefslogtreecommitdiff
path: root/plat/hisilicon
diff options
context:
space:
mode:
authorLeo Yan <leo.yan@linaro.org>2018-01-22 12:40:25 +0800
committerLeo Yan <leo.yan@linaro.org>2018-01-22 13:00:00 +0800
commitb79f7ed03ac0654a479e23bc72a05ab4736ce159 (patch)
treee899ba7550482729905e6f6428cf478da4b06c25 /plat/hisilicon
parentc1edcd935deabaa1b7d28c5c56e4674c05b635f2 (diff)
Hikey960: Enable invalid FIQ handling
When some interrupts are configured as group 0 in GICv2, these interrupts trigger FIQ signal; this results in the Linux kernel panic by reporting log: "Bad mode in FIQ handler detected on CPU0, code 0x00000000 -- Unknown/Uncategorized". Unfortunately from kernel side it has no permission to read the GIC register for group 0 interrupts so we have no chance to get to know which interrupt is configured as secure interrupt and cause the kernel panic. For upper reason, this commit enables FIQ exception handling for SPD_none case. If the system has not enabled SPD the FIQ interrupt is trapped into EL3 and the FIQ handler can report the interrupt number so we can easily narrow down which FIQ introduce unexpected interrupt. After enable SPD we can rely on SPD interrupt route model to handle FIQ. Signed-off-by: Leo Yan <leo.yan@linaro.org>
Diffstat (limited to 'plat/hisilicon')
-rw-r--r--plat/hisilicon/hikey960/hikey960_bl31_setup.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/plat/hisilicon/hikey960/hikey960_bl31_setup.c b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
index f685f9cf..f0d15a35 100644
--- a/plat/hisilicon/hikey960/hikey960_bl31_setup.c
+++ b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
@@ -16,6 +16,8 @@
#include <gicv2.h>
#include <hi3660.h>
#include <hisi_ipc.h>
+#include <interrupt_mgmt.h>
+#include <platform.h>
#include <platform_def.h>
#include "hikey960_def.h"
@@ -167,6 +169,37 @@ void bl31_platform_setup(void)
hisi_ipc_init();
}
+#ifdef SPD_none
+static uint64_t hikey_debug_fiq_handler(uint32_t id,
+ uint32_t flags,
+ void *handle,
+ void *cookie)
+{
+ int intr, intr_raw;
+
+ /* Acknowledge interrupt */
+ intr_raw = plat_ic_acknowledge_interrupt();
+ intr = plat_ic_get_interrupt_id(intr_raw);
+ ERROR("Invalid interrupt: intr=%d\n", intr);
+ console_flush();
+ panic();
+
+ return 0;
+}
+#endif
+
void bl31_plat_runtime_setup(void)
{
+#ifdef SPD_none
+ uint32_t flags;
+ int32_t rc;
+
+ flags = 0;
+ set_interrupt_rm_flag(flags, NON_SECURE);
+ rc = register_interrupt_type_handler(INTR_TYPE_S_EL1,
+ hikey_debug_fiq_handler,
+ flags);
+ if (rc != 0)
+ panic();
+#endif
}