Tegra: handle FIQ interrupts when NS handler is not registered
authorVarun Wadekar <vwadekar@nvidia.com>
Thu, 4 Jan 2018 21:41:27 +0000 (13:41 -0800)
committerVarun Wadekar <vwadekar@nvidia.com>
Thu, 31 Jan 2019 16:46:03 +0000 (08:46 -0800)
This patch updates the secure interrupt handler to mark the interrupt
as complete in case the NS world has not registered a handler.

Change-Id: Iebe952305f7db46375303699b6150611439475df
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
plat/nvidia/tegra/common/tegra_fiq_glue.c

index cab2e5ec583ead2c9f70a675d230e1f13ba25aa8..b036690458a557bfad0060602f5f627e02f9bb3b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -46,33 +46,44 @@ static uint64_t tegra_fiq_interrupt_handler(uint32_t id,
        (void)handle;
        (void)cookie;
 
-       bakery_lock_get(&tegra_fiq_lock);
-
        /*
-        * The FIQ was generated when the execution was in the non-secure
-        * world. Save the context registers to start with.
+        * Read the pending interrupt ID
         */
-       cm_el1_sysregs_context_save(NON_SECURE);
+       irq = plat_ic_get_pending_interrupt_id();
 
-       /*
-        * Save elr_el3 and spsr_el3 from the saved context, and overwrite
-        * the context with the NS fiq_handler_addr and SPSR value.
-        */
-       fiq_state[cpu].elr_el3 = read_ctx_reg((el3state_ctx), (uint32_t)(CTX_ELR_EL3));
-       fiq_state[cpu].spsr_el3 = read_ctx_reg((el3state_ctx), (uint32_t)(CTX_SPSR_EL3));
+       bakery_lock_get(&tegra_fiq_lock);
 
        /*
-        * Set the new ELR to continue execution in the NS world using the
-        * FIQ handler registered earlier.
+        * Jump to NS world only if the NS world's FIQ handler has
+        * been registered
         */
-       assert(ns_fiq_handler_addr != 0ULL);
-       write_ctx_reg((el3state_ctx), (uint32_t)(CTX_ELR_EL3), (ns_fiq_handler_addr));
+       if (ns_fiq_handler_addr != 0U) {
+
+               /*
+                * The FIQ was generated when the execution was in the non-secure
+                * world. Save the context registers to start with.
+                */
+               cm_el1_sysregs_context_save(NON_SECURE);
+
+               /*
+                * Save elr_el3 and spsr_el3 from the saved context, and overwrite
+                * the context with the NS fiq_handler_addr and SPSR value.
+                */
+               fiq_state[cpu].elr_el3 = read_ctx_reg((el3state_ctx), (uint32_t)(CTX_ELR_EL3));
+               fiq_state[cpu].spsr_el3 = read_ctx_reg((el3state_ctx), (uint32_t)(CTX_SPSR_EL3));
+
+               /*
+                * Set the new ELR to continue execution in the NS world using the
+                * FIQ handler registered earlier.
+                */
+               cm_set_elr_el3(NON_SECURE, ns_fiq_handler_addr);
+       }
 
        /*
         * Mark this interrupt as complete to avoid a FIQ storm.
         */
-       irq = plat_ic_acknowledge_interrupt();
        if (irq < 1022U) {
+               (void)plat_ic_acknowledge_interrupt();
                plat_ic_end_of_interrupt(irq);
        }