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 @@ /* 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 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 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 @@ * 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)