diff options
| author | danh-arm <dan.handley@arm.com> | 2018-07-24 14:36:43 +0100 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-07-24 14:36:43 +0100 | 
| commit | 790e6c5b96c4c71958071702f5227bc4f47b3b2a (patch) | |
| tree | 31a566d655ea482c66448b789b3e9d31bcd2bd82 | |
| parent | df0b5a4b71a2259ae90b212fa7527203f81d294d (diff) | |
| parent | 4431aae9734f2e69a5252e8550da1860ecf8cd92 (diff) | |
Merge pull request #1485 from jeenu-arm/ras
Double-fault and fatal error handling support
| -rw-r--r-- | bl31/aarch64/ea_delegate.S | 263 | ||||
| -rw-r--r-- | bl31/aarch64/runtime_exceptions.S | 122 | ||||
| -rw-r--r-- | bl31/bl31.mk | 1 | ||||
| -rw-r--r-- | docs/porting-guide.rst | 100 | ||||
| -rw-r--r-- | include/lib/extensions/ras_arch.h | 57 | ||||
| -rw-r--r-- | plat/common/aarch64/platform_helpers.S | 35 | 
6 files changed, 452 insertions, 126 deletions
| diff --git a/bl31/aarch64/ea_delegate.S b/bl31/aarch64/ea_delegate.S new file mode 100644 index 00000000..9d7c5e8a --- /dev/null +++ b/bl31/aarch64/ea_delegate.S @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#include <assert_macros.S> +#include <asm_macros.S> +#include <assert_macros.S> +#include <context.h> +#include <ea_handle.h> +#include <ras_arch.h> + + +	.globl	handle_lower_el_ea_esb +	.globl	enter_lower_el_sync_ea +	.globl	enter_lower_el_async_ea + + +/* + * Function to delegate External Aborts synchronized by ESB instruction at EL3 + * vector entry. This function assumes GP registers x0-x29 have been saved, and + * are available for use. It delegates the handling of the EA to platform + * handler, and returns only upon successfully handling the EA; otherwise + * panics. On return from this function, the original exception handler is + * expected to resume. + */ +func handle_lower_el_ea_esb +	mov	x0, #ERROR_EA_ESB +	mrs	x1, DISR_EL1 +	b	ea_proceed +endfunc handle_lower_el_ea_esb + + +/* + * This function forms the tail end of Synchronous Exception entry from lower + * EL, and expects to handle only Synchronous External Aborts from lower EL. If + * any other kind of exception is detected, then this function reports unhandled + * exception. + * + * Since it's part of exception vector, this function doesn't expect any GP + * registers to have been saved. It delegates the handling of the EA to platform + * handler, and upon successfully handling the EA, exits EL3; otherwise panics. + */ +func enter_lower_el_sync_ea +	/* +	 * Explicitly save x30 so as to free up a register and to enable +	 * branching. +	 */ +	str	x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + +	mrs	x30, esr_el3 +	ubfx	x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH + +	/* Check for I/D aborts from lower EL */ +	cmp	x30, #EC_IABORT_LOWER_EL +	b.eq	1f + +	cmp	x30, #EC_DABORT_LOWER_EL +	b.ne	2f + +1: +	/* Test for EA bit in the instruction syndrome */ +	mrs	x30, esr_el3 +	tbz	x30, #ESR_ISS_EABORT_EA_BIT, 2f + +	/* Save GP registers */ +	bl	save_gp_registers + +	/* Setup exception class and syndrome arguments for platform handler */ +	mov	x0, #ERROR_EA_SYNC +	mrs	x1, esr_el3 +	adr	x30, el3_exit +	b	delegate_sync_ea + +2: +	/* Synchronous exceptions other than the above are assumed to be EA */ +	ldr	x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] +	no_ret	report_unhandled_exception +endfunc enter_lower_el_sync_ea + + +/* + * This function handles SErrors from lower ELs. + * + * Since it's part of exception vector, this function doesn't expect any GP + * registers to have been saved. It delegates the handling of the EA to platform + * handler, and upon successfully handling the EA, exits EL3; otherwise panics. + */ +func enter_lower_el_async_ea +	/* +	 * Explicitly save x30 so as to free up a register and to enable +	 * branching +	 */ +	str	x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + +	/* Save GP registers */ +	bl	save_gp_registers + +	/* Setup exception class and syndrome arguments for platform handler */ +	mov	x0, #ERROR_EA_ASYNC +	mrs	x1, esr_el3 +	adr	x30, el3_exit +	b	delegate_async_ea +endfunc enter_lower_el_async_ea + + +/* + * Prelude for Synchronous External Abort handling. This function assumes that + * all GP registers have been saved by the caller. + * + * x0: EA reason + * x1: EA syndrome + */ +func delegate_sync_ea +#if RAS_EXTENSION +	/* +	 * Check for Uncontainable error type. If so, route to the platform +	 * fatal error handler rather than the generic EA one. +	 */ +	ubfx    x2, x1, #EABORT_SET_SHIFT, #EABORT_SET_WIDTH +	cmp     x2, #ERROR_STATUS_SET_UC +	b.ne    1f + +	/* Check fault status code */ +	ubfx    x3, x1, #EABORT_DFSC_SHIFT, #EABORT_DFSC_WIDTH +	cmp     x3, #SYNC_EA_FSC +	b.ne    1f + +	no_ret  plat_handle_uncontainable_ea +1: +#endif + +	b       ea_proceed +endfunc delegate_sync_ea + + +/* + * Prelude for Asynchronous External Abort handling. This function assumes that + * all GP registers have been saved by the caller. + * + * x0: EA reason + * x1: EA syndrome + */ +func delegate_async_ea +#if RAS_EXTENSION +	/* +	 * Check for Implementation Defined Syndrome. If so, skip checking +	 * Uncontainable error type from the syndrome as the format is unknown. +	 */ +	tbnz	x1, #SERROR_IDS_BIT, 1f + +	/* +	 * Check for Uncontainable error type. If so, route to the platform +	 * fatal error handler rather than the generic EA one. +	 */ +	ubfx	x2, x1, #EABORT_AET_SHIFT, #EABORT_AET_WIDTH +	cmp	x2, #ERROR_STATUS_UET_UC +	b.ne	1f + +	/* Check DFSC for SError type */ +	ubfx	x3, x1, #EABORT_DFSC_SHIFT, #EABORT_DFSC_WIDTH +	cmp	x3, #DFSC_SERROR +	b.ne	1f + +	no_ret	plat_handle_uncontainable_ea +1: +#endif + +	b	ea_proceed +endfunc delegate_async_ea + + +/* + * Delegate External Abort handling to platform's EA handler. This function + * assumes that all GP registers have been saved by the caller. + * + * x0: EA reason + * x1: EA syndrome + */ +func ea_proceed +	/* +	 * If the ESR loaded earlier is not zero, we were processing an EA +	 * already, and this is a double fault. +	 */ +	ldr	x5, [sp, #CTX_EL3STATE_OFFSET + CTX_ESR_EL3] +	cbz	x5, 1f +	no_ret	plat_handle_double_fault + +1: +	/* Save EL3 state */ +	mrs	x2, spsr_el3 +	mrs	x3, elr_el3 +	stp	x2, x3, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3] + +	/* +	 * Save ESR as handling might involve lower ELs, and returning back to +	 * EL3 from there would trample the original ESR. +	 */ +	mrs	x4, scr_el3 +	mrs	x5, esr_el3 +	stp	x4, x5, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3] + +	/* +	 * Setup rest of arguments, and call platform External Abort handler. +	 * +	 * x0: EA reason (already in place) +	 * x1: Exception syndrome (already in place). +	 * x2: Cookie (unused for now). +	 * x3: Context pointer. +	 * x4: Flags (security state from SCR for now). +	 */ +	mov	x2, xzr +	mov	x3, sp +	ubfx	x4, x4, #0, #1 + +	/* Switch to runtime stack */ +	ldr	x5, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] +	msr	spsel, #0 +	mov	sp, x5 + +	mov	x29, x30 +#if ENABLE_ASSERTIONS +	/* Stash the stack pointer */ +	mov	x28, sp +#endif +	bl	plat_ea_handler + +#if ENABLE_ASSERTIONS +	/* +	 * Error handling flows might involve long jumps; so upon returning from +	 * the platform error handler, validate that the we've completely +	 * unwound the stack. +	 */ +	mov	x27, sp +	cmp	x28, x27 +	ASM_ASSERT(eq) +#endif + +	/* Make SP point to context */ +	msr	spsel, #1 + +	/* Restore EL3 state and ESR */ +	ldp	x1, x2, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3] +	msr	spsr_el3, x1 +	msr	elr_el3, x2 + +	/* Restore ESR_EL3 and SCR_EL3 */ +	ldp	x3, x4, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3] +	msr	scr_el3, x3 +	msr	esr_el3, x4 + +#if ENABLE_ASSERTIONS +	cmp	x4, xzr +	ASM_ASSERT(ne) +#endif + +	/* Clear ESR storage */ +	str	xzr, [sp, #CTX_EL3STATE_OFFSET + CTX_ESR_EL3] + +	ret	x29 +endfunc ea_proceed diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S index 12f9f109..54db6814 100644 --- a/bl31/aarch64/runtime_exceptions.S +++ b/bl31/aarch64/runtime_exceptions.S @@ -66,9 +66,7 @@  	/* Save GP registers and restore them afterwards */  	bl	save_gp_registers -	mov	x0, #ERROR_EA_ESB -	mrs	x1, DISR_EL1 -	bl	delegate_ea +	bl	handle_lower_el_ea_esb  	bl	restore_gp_registers  1: @@ -80,27 +78,6 @@  #endif  	.endm -	/* -	 * Handle External Abort by delegating to the platform's EA handler. -	 * Once the platform handler returns, the macro exits EL3 and returns to -	 * where the abort was taken from. -	 * -	 * This macro assumes that x30 is available for use. -	 * -	 * 'abort_type' is a constant passed to the platform handler, indicating -	 * the cause of the External Abort. -	 */ -	.macro handle_ea abort_type -	/* Save GP registers */ -	bl	save_gp_registers - -	/* Setup exception class and syndrome arguments for platform handler */ -	mov	x0, \abort_type -	mrs	x1, esr_el3 -	adr	x30, el3_exit -	b	delegate_ea -	.endm -  	/* ---------------------------------------------------------------------  	 * This macro handles Synchronous exceptions.  	 * Only SMC exceptions are supported. @@ -130,23 +107,9 @@  	cmp	x30, #EC_AARCH64_SMC  	b.eq	smc_handler64 -	/* Check for I/D aborts from lower EL */ -	cmp	x30, #EC_IABORT_LOWER_EL -	b.eq	1f - -	cmp	x30, #EC_DABORT_LOWER_EL -	b.ne	2f - -1: -	/* Test for EA bit in the instruction syndrome */ -	mrs	x30, esr_el3 -	tbz	x30, #ESR_ISS_EABORT_EA_BIT, 2f -	handle_ea #ERROR_EA_SYNC - -2: -	/* Other kinds of synchronous exceptions are not handled */ +	/* Synchronous exceptions other than the above are assumed to be EA */  	ldr	x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] -	b	report_unhandled_exception +	b	enter_lower_el_sync_ea  	.endm @@ -250,7 +213,7 @@ end_vector_entry fiq_sp_el0  vector_entry serror_sp_el0 -	b	report_unhandled_exception +	no_ret	plat_handle_el3_ea  end_vector_entry serror_sp_el0  	/* --------------------------------------------------------------------- @@ -276,7 +239,7 @@ vector_entry fiq_sp_elx  end_vector_entry fiq_sp_elx  vector_entry serror_sp_elx -	b	report_unhandled_exception +	no_ret	plat_handle_el3_ea  end_vector_entry serror_sp_elx  	/* --------------------------------------------------------------------- @@ -306,13 +269,7 @@ end_vector_entry fiq_aarch64  vector_entry serror_aarch64  	msr	daifclr, #DAIF_ABT_BIT - -	/* -	 * Explicitly save x30 so as to free up a register and to enable -	 * branching -	 */ -	str	x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] -	handle_ea #ERROR_EA_ASYNC +	b	enter_lower_el_async_ea  end_vector_entry serror_aarch64  	/* --------------------------------------------------------------------- @@ -342,13 +299,7 @@ end_vector_entry fiq_aarch32  vector_entry serror_aarch32  	msr	daifclr, #DAIF_ABT_BIT - -	/* -	 * Explicitly save x30 so as to free up a register and to enable -	 * branching -	 */ -	str	x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] -	handle_ea #ERROR_EA_ASYNC +	b	enter_lower_el_async_ea  end_vector_entry serror_aarch32 @@ -525,62 +476,3 @@ rt_svc_fw_critical_error:  	msr	spsel, #1  	no_ret	report_unhandled_exception  endfunc smc_handler - -/* - * Delegate External Abort handling to platform's EA handler. This function - * assumes that all GP registers have been saved by the caller. - * - * x0: EA reason - * x1: EA syndrome - */ -func delegate_ea -	/* Save EL3 state */ -	mrs	x2, spsr_el3 -	mrs	x3, elr_el3 -	stp	x2, x3, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3] - -	/* -	 * Save ESR as handling might involve lower ELs, and returning back to -	 * EL3 from there would trample the original ESR. -	 */ -	mrs	x4, scr_el3 -	mrs	x5, esr_el3 -	stp	x4, x5, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3] - -	/* -	 * Setup rest of arguments, and call platform External Abort handler. -	 * -	 * x0: EA reason (already in place) -	 * x1: Exception syndrome (already in place). -	 * x2: Cookie (unused for now). -	 * x3: Context pointer. -	 * x4: Flags (security state from SCR for now). -	 */ -	mov	x2, xzr -	mov	x3, sp -	ubfx	x4, x4, #0, #1 - -	/* Switch to runtime stack */ -	ldr	x5, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] -	msr	spsel, #0 -	mov	sp, x5 - -	mov	x29, x30 -	bl	plat_ea_handler -	mov	x30, x29 - -	/* Make SP point to context */ -	msr	spsel, #1 - -	/* Restore EL3 state */ -	ldp	x1, x2, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3] -	msr	spsr_el3, x1 -	msr	elr_el3, x2 - -	/* Restore ESR_EL3 and SCR_EL3 */ -	ldp	x3, x4, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3] -	msr	scr_el3, x3 -	msr	esr_el3, x4 - -	ret -endfunc delegate_ea diff --git a/bl31/bl31.mk b/bl31/bl31.mk index 307ddab6..bff96538 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -19,6 +19,7 @@ BL31_SOURCES		+=	bl31/bl31_main.c				\  				bl31/interrupt_mgmt.c				\  				bl31/aarch64/bl31_entrypoint.S			\  				bl31/aarch64/crash_reporting.S			\ +				bl31/aarch64/ea_delegate.S			\  				bl31/aarch64/runtime_exceptions.S		\  				bl31/bl31_context_mgmt.c			\  				common/runtime_svc.c				\ diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst index 5462cc1e..a7a88f64 100644 --- a/docs/porting-guide.rst +++ b/docs/porting-guide.rst @@ -2850,6 +2850,106 @@ you can keep the default implementation here (which calls ``console_flush()``).  If you're trying to debug crashes in BL1, you can call the console_xx_core_flush  function exported by some console drivers from here. +Extternal Abort handling and RAS Support +---------------------------------------- + +Function : plat_ea_handler +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + +    Argument : int +    Argument : uint64_t +    Argument : void * +    Argument : void * +    Argument : uint64_t +    Return   : void + +This function is invoked by the RAS framework for the platform to handle an +External Abort received at EL3. The intention of the function is to attempt to +resolve the cause of External Abort and return; if that's not possible, to +initiate orderly shutdown of the system. + +The first parameter (``int ea_reason``) indicates the reason for External Abort. +Its value is one of ``ERROR_EA_*`` constants defined in ``ea_handle.h``. + +The second parameter (``uint64_t syndrome``) is the respective syndrome +presented to EL3 after having received the External Abort. Depending on the +nature of the abort (as can be inferred from the ``ea_reason`` parameter), this +can be the content of either ``ESR_EL3`` or ``DISR_EL1``. + +The third parameter (``void *cookie``) is unused for now. The fourth parameter +(``void *handle``) is a pointer to the preempted context. The fifth parameter +(``uint64_t flags``) indicates the preempted security state. These parameters +are received from the top-level exception handler. + +If ``RAS_EXTENSION`` is set to ``1``, the default implementation of this +function iterates through RAS handlers registered by the platform. If any of the +RAS handlers resolve the External Abort, no further action is taken. + +If ``RAS_EXTENSION`` is set to ``0``, or if none of the platform RAS handlers +could resolve the External Abort, the default implementation prints an error +message, and panics. + +Function : plat_handle_uncontainable_ea +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + +    Argument : int +    Argument : uint64_t +    Return   : void + +This function is invoked by the RAS framework when an External Abort of +Uncontainable type is received at EL3. Due to the critical nature of +Uncontainable errors, the intention of this function is to initiate orderly +shutdown of the system, and is not expected to return. + +This function must be implemented in assembly. + +The first and second parameters are the same as that of ``plat_ea_handler``. + +The default implementation of this function calls +``report_unhandled_exception``. + +Function : plat_handle_double_fault +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + +    Argument : int +    Argument : uint64_t +    Return   : void + +This function is invoked by the RAS framework when another External Abort is +received at EL3 while one is already being handled. I.e., a call to +``plat_ea_handler`` is outstanding. Due to its critical nature, the intention of +this function is to initiate orderly shutdown of the system, and is not expected +recover or return. + +This function must be implemented in assembly. + +The first and second parameters are the same as that of ``plat_ea_handler``. + +The default implementation of this function calls +``report_unhandled_exception``. + +Function : plat_handle_el3_ea +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + +    Return   : void + +This function is invoked when an External Abort is received while executing in +EL3. Due to its critical nature, the intention of this function is to initiate +orderly shutdown of the system, and is not expected recover or return. + +This function must be implemented in assembly. + +The default implementation of this function calls +``report_unhandled_exception``. +  Build flags  ----------- diff --git a/include/lib/extensions/ras_arch.h b/include/lib/extensions/ras_arch.h index 7d210531..6ec4da80 100644 --- a/include/lib/extensions/ras_arch.h +++ b/include/lib/extensions/ras_arch.h @@ -4,15 +4,8 @@   * SPDX-License-Identifier: BSD-3-Clause   */ -#ifndef __RAS_H__ -#define __RAS_H__ - -#include <arch.h> -#include <arch_helpers.h> -#include <assert.h> -#include <context.h> -#include <mmio.h> -#include <stdint.h> +#ifndef RAS_ARCH_H +#define RAS_ARCH_H  /*   * Size of nodes implementing Standard Error Records - currently only 4k is @@ -146,12 +139,53 @@  #define ERR_CTLR_ENABLE_FIELD(_ctlr, _field) \  	ERR_CTLR_SET_FIELD(_ctlr, _field, ERR_CTLR_ ##_field ##_MASK) -/* Uncorrected error types */ +/* Uncorrected error types for Asynchronous exceptions */  #define ERROR_STATUS_UET_UC	0x0	/* Uncontainable */  #define ERROR_STATUS_UET_UEU	0x1	/* Unrecoverable */  #define ERROR_STATUS_UET_UEO	0x2	/* Restable */  #define ERROR_STATUS_UET_UER	0x3	/* Recoverable */ +/* Error types for Synchronous exceptions */ +#define ERROR_STATUS_SET_UER	0x0	/* Recoverable */ +#define ERROR_STATUS_SET_UEO	0x1	/* Restable */ +#define ERROR_STATUS_SET_UC	0x2     /* Uncontainable */ +#define ERROR_STATUS_SET_CE	0x3     /* Corrected */ + +/* Implementation Defined Syndrome bit in ESR */ +#define SERROR_IDS_BIT		U(24) + +/* + * Asynchronous Error Type in exception syndrome. The field has same values in + * both DISR_EL1 and ESR_EL3 for SError. + */ +#define EABORT_AET_SHIFT	U(10) +#define EABORT_AET_WIDTH	U(3) +#define EABORT_AET_MASK		U(0x7) + +/* DFSC field in Asynchronous exception syndrome */ +#define EABORT_DFSC_SHIFT	U(0) +#define EABORT_DFSC_WIDTH	U(6) +#define EABORT_DFSC_MASK	U(0x3f) + +/* Synchronous Error Type in exception syndrome. */ +#define EABORT_SET_SHIFT	U(11) +#define EABORT_SET_WIDTH	U(2) +#define EABORT_SET_MASK		U(0x3) + +/* DFSC code for SErrors */ +#define DFSC_SERROR		0x11 + +/* I/DFSC code for synchronous external abort */ +#define SYNC_EA_FSC		0x10 + +#ifndef __ASSEMBLY__ + +#include <arch.h> +#include <arch_helpers.h> +#include <assert.h> +#include <context.h> +#include <mmio.h> +#include <stdint.h>  /*   * Standard Error Record accessors for memory-mapped registers. @@ -221,5 +255,6 @@ static inline void ser_sys_select_record(unsigned int idx)  /* Library functions to probe Standard Error Record */  int ser_probe_memmap(uintptr_t base, unsigned int size_num_k, int *probe_data);  int ser_probe_sysreg(unsigned int idx_start, unsigned int num_idx, int *probe_data); +#endif /* __ASSEMBLY__ */ -#endif /* __RAS_H__ */ +#endif /* RAS_ARCH_H */ diff --git a/plat/common/aarch64/platform_helpers.S b/plat/common/aarch64/platform_helpers.S index a413f5fd..a5d26c01 100644 --- a/plat/common/aarch64/platform_helpers.S +++ b/plat/common/aarch64/platform_helpers.S @@ -20,6 +20,10 @@  	.weak	bl31_plat_enable_mmu  	.weak	bl32_plat_enable_mmu +	.weak	plat_handle_uncontainable_ea +	.weak	plat_handle_double_fault +	.weak	plat_handle_el3_ea +  #if !ENABLE_PLAT_COMPAT  	.globl	platform_get_core_pos @@ -186,3 +190,34 @@ endfunc bl31_plat_enable_mmu  func bl32_plat_enable_mmu  	b	enable_mmu_direct_el1  endfunc bl32_plat_enable_mmu + + +	/* ----------------------------------------------------- +	 * Platform handler for Uncontainable External Abort. +	 * +	 * x0: EA reason +	 * x1: EA syndrome +	 * ----------------------------------------------------- +	 */ +func plat_handle_uncontainable_ea +	b	report_unhandled_exception +endfunc plat_handle_uncontainable_ea + +	/* ----------------------------------------------------- +	 * Platform handler for Double Fault. +	 * +	 * x0: EA reason +	 * x1: EA syndrome +	 * ----------------------------------------------------- +	 */ +func plat_handle_double_fault +	b	report_unhandled_exception +endfunc plat_handle_double_fault + +	/* ----------------------------------------------------- +	 * Platform handler for EL3 External Abort. +	 * ----------------------------------------------------- +	 */ +func plat_handle_el3_ea +	b	report_unhandled_exception +endfunc plat_handle_el3_ea | 
