aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bl31/aarch64/runtime_exceptions.S49
-rw-r--r--drivers/arm/gic/arm_gic.c6
-rw-r--r--include/drivers/arm/gic_v2.h3
3 files changed, 35 insertions, 23 deletions
diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S
index accb11b..bbc7f1b 100644
--- a/bl31/aarch64/runtime_exceptions.S
+++ b/bl31/aarch64/runtime_exceptions.S
@@ -79,6 +79,14 @@
str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
bl save_gp_registers
+ /*
+ * Save the EL3 system registers needed to return from
+ * this exception.
+ */
+ mrs x0, spsr_el3
+ mrs x1, elr_el3
+ stp x0, x1, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
+
/* Switch to the runtime stack i.e. SP_EL0 */
ldr x2, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP]
mov x20, sp
@@ -96,13 +104,29 @@
/*
* Get the registered handler for this interrupt type. A
- * NULL return value implies that an interrupt was generated
- * for which there is no handler registered or the interrupt
- * was routed incorrectly. This is a problem of the framework
- * so report it as an error.
+ * NULL return value could be 'cause of the following
+ * conditions:
+ *
+ * a. An interrupt of a type was routed correctly but a
+ * handler for its type was not registered.
+ *
+ * b. An interrupt of a type was not routed correctly so
+ * a handler for its type was not registered.
+ *
+ * c. An interrupt of a type was routed correctly to EL3,
+ * but was deasserted before its pending state could
+ * be read. Another interrupt of a different type pended
+ * at the same time and its type was reported as pending
+ * instead. However, a handler for this type was not
+ * registered.
+ *
+ * a. and b. can only happen due to a programming error.
+ * The occurrence of c. could be beyond the control of
+ * Trusted Firmware. It makes sense to return from this
+ * exception instead of reporting an error.
*/
bl get_interrupt_type_handler
- cbz x0, interrupt_error_\label
+ cbz x0, interrupt_exit_\label
mov x21, x0
mov x0, #INTR_ID_UNAVAILABLE
@@ -117,14 +141,6 @@
b.eq interrupt_exit_\label
#endif
- /*
- * Save the EL3 system registers needed to return from
- * this exception.
- */
- mrs x3, spsr_el3
- mrs x4, elr_el3
- stp x3, x4, [x20, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
-
/* Set the current security state in the 'flags' parameter */
mrs x2, scr_el3
ubfx x1, x2, #0, #1
@@ -142,13 +158,6 @@ interrupt_exit_\label:
/* Return from exception, possibly in a different security state */
b el3_exit
- /*
- * This label signifies a problem with the interrupt management
- * framework where it is not safe to go back to the instruction
- * where the interrupt was generated.
- */
-interrupt_error_\label:
- bl report_unhandled_interrupt
.endm
diff --git a/drivers/arm/gic/arm_gic.c b/drivers/arm/gic/arm_gic.c
index 2888e71..5217471 100644
--- a/drivers/arm/gic/arm_gic.c
+++ b/drivers/arm/gic/arm_gic.c
@@ -401,7 +401,7 @@ uint32_t arm_gic_get_pending_interrupt_type(void)
uint32_t id;
assert(g_gicc_base);
- id = gicc_read_hppir(g_gicc_base);
+ id = gicc_read_hppir(g_gicc_base) & INT_ID_MASK;
/* Assume that all secure interrupts are S-EL1 interrupts */
if (id < 1022)
@@ -423,7 +423,7 @@ uint32_t arm_gic_get_pending_interrupt_id(void)
uint32_t id;
assert(g_gicc_base);
- id = gicc_read_hppir(g_gicc_base);
+ id = gicc_read_hppir(g_gicc_base) & INT_ID_MASK;
if (id < 1022)
return id;
@@ -435,7 +435,7 @@ uint32_t arm_gic_get_pending_interrupt_id(void)
* Find out which non-secure interrupt it is under the assumption that
* the GICC_CTLR.AckCtl bit is 0.
*/
- return gicc_read_ahppir(g_gicc_base);
+ return gicc_read_ahppir(g_gicc_base) & INT_ID_MASK;
}
/*******************************************************************************
diff --git a/include/drivers/arm/gic_v2.h b/include/drivers/arm/gic_v2.h
index a2d3eee..54276b8 100644
--- a/include/drivers/arm/gic_v2.h
+++ b/include/drivers/arm/gic_v2.h
@@ -99,6 +99,9 @@
#define GICC_DIR 0x1000
#define GICC_PRIODROP GICC_EOIR
+/* Common CPU Interface definitions */
+#define INT_ID_MASK 0x3ff
+
/* GICC_CTLR bit definitions */
#define EOI_MODE_NS (1 << 10)
#define EOI_MODE_S (1 << 9)