From b79f7ed03ac0654a479e23bc72a05ab4736ce159 Mon Sep 17 00:00:00 2001 From: Leo Yan <leo.yan@linaro.org> Date: Mon, 22 Jan 2018 12:40:25 +0800 Subject: [PATCH] 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> --- plat/hisilicon/hikey960/hikey960_bl31_setup.c | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/plat/hisilicon/hikey960/hikey960_bl31_setup.c b/plat/hisilicon/hikey960/hikey960_bl31_setup.c index f685f9cfa..f0d15a358 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 } -- GitLab