mirror of
https://github.com/CTCaer/switch-l4t-atf.git
synced 2024-12-01 05:40:27 +00:00
AArch64: Introduce External Abort handling
At present, any External Abort routed to EL3 is reported as an unhandled exception and cause a panic. This patch enables ARM Trusted Firmware to handle External Aborts routed to EL3. With this patch, when an External Abort is received at EL3, its handling is delegated to plat_ea_handler() function. Platforms can provide their own implementation of this function. This patch adds a weak definition of the said function that prints out a message and just panics. In order to support handling External Aborts at EL3, the build option HANDLE_EA_EL3_FIRST must be set to 1. Before this patch, HANDLE_EA_EL3_FIRST wasn't passed down to compilation; this patch fixes that too. Change-Id: I4d07b7e65eb191ff72d63b909ae9512478cd01a1 Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
This commit is contained in:
parent
ef653d93cc
commit
76454abf4a
2
Makefile
2
Makefile
@ -517,6 +517,7 @@ $(eval $(call assert_boolean,ENABLE_SVE_FOR_NS))
|
||||
$(eval $(call assert_boolean,ERROR_DEPRECATED))
|
||||
$(eval $(call assert_boolean,GENERATE_COT))
|
||||
$(eval $(call assert_boolean,GICV2_G0_FOR_EL3))
|
||||
$(eval $(call assert_boolean,HANDLE_EA_EL3_FIRST))
|
||||
$(eval $(call assert_boolean,HW_ASSISTED_COHERENCY))
|
||||
$(eval $(call assert_boolean,LOAD_IMAGE_V2))
|
||||
$(eval $(call assert_boolean,MULTI_CONSOLE_API))
|
||||
@ -563,6 +564,7 @@ $(eval $(call add_define,ENABLE_SPM))
|
||||
$(eval $(call add_define,ENABLE_SVE_FOR_NS))
|
||||
$(eval $(call add_define,ERROR_DEPRECATED))
|
||||
$(eval $(call add_define,GICV2_G0_FOR_EL3))
|
||||
$(eval $(call add_define,HANDLE_EA_EL3_FIRST))
|
||||
$(eval $(call add_define,HW_ASSISTED_COHERENCY))
|
||||
$(eval $(call add_define,LOAD_IMAGE_V2))
|
||||
$(eval $(call add_define,LOG_LEVEL))
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <asm_macros.S>
|
||||
#include <context.h>
|
||||
#include <cpu_data.h>
|
||||
#include <ea_handle.h>
|
||||
#include <interrupt_mgmt.h>
|
||||
#include <platform_def.h>
|
||||
#include <runtime_svc.h>
|
||||
@ -35,6 +36,27 @@
|
||||
.globl fiq_aarch32
|
||||
.globl serror_aarch32
|
||||
|
||||
/*
|
||||
* 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.
|
||||
@ -69,6 +91,20 @@
|
||||
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 */
|
||||
ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
|
||||
b report_unhandled_exception
|
||||
@ -232,11 +268,14 @@ vector_entry fiq_aarch64
|
||||
check_vector_size fiq_aarch64
|
||||
|
||||
vector_entry serror_aarch64
|
||||
msr daifclr, #DAIF_ABT_BIT
|
||||
|
||||
/*
|
||||
* SError exceptions from lower ELs are not currently supported.
|
||||
* Report their occurrence.
|
||||
* Explicitly save x30 so as to free up a register and to enable
|
||||
* branching
|
||||
*/
|
||||
b report_unhandled_exception
|
||||
str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
|
||||
handle_ea #ERROR_EA_ASYNC
|
||||
check_vector_size serror_aarch64
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
@ -262,11 +301,14 @@ vector_entry fiq_aarch32
|
||||
check_vector_size fiq_aarch32
|
||||
|
||||
vector_entry serror_aarch32
|
||||
msr daifclr, #DAIF_ABT_BIT
|
||||
|
||||
/*
|
||||
* SError exceptions from lower ELs are not currently supported.
|
||||
* Report their occurrence.
|
||||
* Explicitly save x30 so as to free up a register and to enable
|
||||
* branching
|
||||
*/
|
||||
b report_unhandled_exception
|
||||
str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
|
||||
handle_ea #ERROR_EA_ASYNC
|
||||
check_vector_size serror_aarch32
|
||||
|
||||
|
||||
@ -443,3 +485,62 @@ 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
|
||||
|
18
include/bl31/ea_handle.h
Normal file
18
include/bl31/ea_handle.h
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __EA_HANDLE_H__
|
||||
#define __EA_HANDLE_H__
|
||||
|
||||
/* Constants indicating the reason for an External Abort */
|
||||
|
||||
/* External Abort received at SError vector */
|
||||
#define ERROR_EA_ASYNC 0
|
||||
|
||||
/* Synchronous External Abort received at Synchronous exception vector */
|
||||
#define ERROR_EA_SYNC 1
|
||||
|
||||
#endif /* __EA_HANDLE_H__ */
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
@ -528,6 +528,12 @@
|
||||
#define EC_AARCH64_FP U(0x2c)
|
||||
#define EC_SERROR U(0x2f)
|
||||
|
||||
/*
|
||||
* External Abort bit in Instruction and Data Aborts synchronous exception
|
||||
* syndromes.
|
||||
*/
|
||||
#define ESR_ISS_EABORT_EA_BIT U(9)
|
||||
|
||||
#define EC_BITS(x) (((x) >> ESR_EC_SHIFT) & ESR_EC_MASK)
|
||||
|
||||
/* Reset bit inside the Reset management register for EL3 (RMR_EL3) */
|
||||
|
@ -7,6 +7,8 @@
|
||||
#ifndef __CONTEXT_H__
|
||||
#define __CONTEXT_H__
|
||||
|
||||
#include <utils_def.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Constants that allow assembler code to access members of and the 'gp_regs'
|
||||
* structure at their correct offsets.
|
||||
@ -53,10 +55,12 @@
|
||||
******************************************************************************/
|
||||
#define CTX_EL3STATE_OFFSET (CTX_GPREGS_OFFSET + CTX_GPREGS_END)
|
||||
#define CTX_SCR_EL3 U(0x0)
|
||||
#define CTX_RUNTIME_SP U(0x8)
|
||||
#define CTX_SPSR_EL3 U(0x10)
|
||||
#define CTX_ELR_EL3 U(0x18)
|
||||
#define CTX_EL3STATE_END U(0x20)
|
||||
#define CTX_ESR_EL3 U(0x8)
|
||||
#define CTX_RUNTIME_SP U(0x10)
|
||||
#define CTX_SPSR_EL3 U(0x18)
|
||||
#define CTX_ELR_EL3 U(0x20)
|
||||
#define CTX_UNUSED U(0x28)
|
||||
#define CTX_EL3STATE_END U(0x30)
|
||||
|
||||
/*******************************************************************************
|
||||
* Constants that allow assembler code to access members of and the
|
||||
|
@ -124,6 +124,9 @@ int plat_sdei_validate_entry_point(uintptr_t ep, unsigned int client_mode);
|
||||
void plat_sdei_handle_masked_trigger(uint64_t mpidr, unsigned int intr);
|
||||
#endif
|
||||
|
||||
void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
|
||||
void *handle, uint64_t flags);
|
||||
|
||||
/*
|
||||
* The following function is mandatory when the
|
||||
* firmware update feature is used.
|
||||
|
@ -92,6 +92,10 @@ GENERATE_COT := 0
|
||||
# default, they are for Secure EL1.
|
||||
GICV2_G0_FOR_EL3 := 0
|
||||
|
||||
# Route External Aborts to EL3. Disabled by default; External Aborts are handled
|
||||
# by lower ELs.
|
||||
HANDLE_EA_EL3_FIRST := 0
|
||||
|
||||
# Whether system coherency is managed in hardware, without explicit software
|
||||
# operations.
|
||||
HW_ASSISTED_COHERENCY := 0
|
||||
|
@ -28,6 +28,8 @@
|
||||
#pragma weak plat_sdei_validate_entry_point
|
||||
#endif
|
||||
|
||||
#pragma weak plat_ea_handler
|
||||
|
||||
void bl31_plat_enable_mmu(uint32_t flags)
|
||||
{
|
||||
enable_mmu_el3(flags);
|
||||
@ -105,3 +107,13 @@ int plat_sdei_validate_entry_point(uintptr_t ep, unsigned int client_mode)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* RAS functions common to AArch64 ARM platforms */
|
||||
void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
|
||||
void *handle, uint64_t flags)
|
||||
{
|
||||
ERROR("Unhandled External Abort received on 0x%lx at EL3!\n",
|
||||
read_mpidr_el1());
|
||||
ERROR(" exception reason=%u syndrome=0x%lx\n", ea_reason, syndrome);
|
||||
panic();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user