diff --git a/bl1/aarch64/bl1_arch_setup.c b/bl1/aarch64/bl1_arch_setup.c index d4be9d6be..7085f7789 100644 --- a/bl1/aarch64/bl1_arch_setup.c +++ b/bl1/aarch64/bl1_arch_setup.c @@ -48,11 +48,19 @@ void bl1_arch_setup(void) write_sctlr(tmp_reg); /* - * Enable HVCs, route FIQs to EL3, set the next EL to be aarch64 + * Enable HVCs, route FIQs to EL3, set the next EL to be AArch64, route + * external abort and SError interrupts to EL3 */ - tmp_reg = SCR_RES1_BITS | SCR_RW_BIT | SCR_HCE_BIT | SCR_FIQ_BIT; + tmp_reg = SCR_RES1_BITS | SCR_RW_BIT | SCR_HCE_BIT | SCR_EA_BIT | + SCR_FIQ_BIT; write_scr(tmp_reg); + /* + * Enable SError and Debug exceptions + */ + enable_serror(); + enable_debug_exceptions(); + /* Do not trap coprocessor accesses from lower ELs to EL3 */ write_cptr_el3(0); diff --git a/bl31/aarch64/bl31_arch_setup.c b/bl31/aarch64/bl31_arch_setup.c index f6fa088f1..238af7bdf 100644 --- a/bl31/aarch64/bl31_arch_setup.c +++ b/bl31/aarch64/bl31_arch_setup.c @@ -49,12 +49,19 @@ void bl31_arch_setup(void) write_sctlr(tmp_reg); /* - * Enable HVCs, allow NS to mask CPSR.A, route FIQs to EL3, set the - * next EL to be aarch64 + * Enable HVCs, route FIQs to EL3, set the next EL to be AArch64, route + * external abort and SError interrupts to EL3 */ - tmp_reg = SCR_RES1_BITS | SCR_RW_BIT | SCR_HCE_BIT | SCR_FIQ_BIT; + tmp_reg = SCR_RES1_BITS | SCR_RW_BIT | SCR_HCE_BIT | SCR_EA_BIT | + SCR_FIQ_BIT; write_scr(tmp_reg); + /* + * Enable SError and Debug exceptions + */ + enable_serror(); + enable_debug_exceptions(); + /* Do not trap coprocessor accesses from lower ELs to EL3 */ write_cptr_el3(0); diff --git a/common/psci/psci_afflvl_suspend.c b/common/psci/psci_afflvl_suspend.c index 030f15dde..9a2c0cfb4 100644 --- a/common/psci/psci_afflvl_suspend.c +++ b/common/psci/psci_afflvl_suspend.c @@ -82,6 +82,8 @@ static int psci_afflvl0_suspend(unsigned long mpidr, psci_secure_context[index].tcr = read_tcr(); psci_secure_context[index].ttbr = read_ttbr0(); psci_secure_context[index].vbar = read_vbar(); + psci_secure_context[index].pstate = + read_daif() & (DAIF_ABT_BIT | DAIF_DBG_BIT); /* Set the secure world (EL3) re-entry point after BL1 */ psci_entrypoint = (unsigned long) psci_aff_suspend_finish_entry; @@ -370,6 +372,7 @@ static unsigned int psci_afflvl0_suspend_finish(unsigned long mpidr, * context in the right order. */ write_vbar(psci_secure_context[index].vbar); + write_daif(read_daif() | psci_secure_context[index].pstate); write_mair(psci_secure_context[index].mair); write_tcr(psci_secure_context[index].tcr); write_ttbr0(psci_secure_context[index].ttbr); diff --git a/common/psci/psci_private.h b/common/psci/psci_private.h index 48d40d0fd..6505adf36 100644 --- a/common/psci/psci_private.h +++ b/common/psci/psci_private.h @@ -64,6 +64,7 @@ typedef struct { unsigned long tcr; unsigned long ttbr; unsigned long vbar; + unsigned long pstate; } secure_context; /******************************************************************************* diff --git a/docs/change-log.md b/docs/change-log.md index 1f2d12c4b..61499c78b 100644 --- a/docs/change-log.md +++ b/docs/change-log.md @@ -17,6 +17,9 @@ Detailed changes since last release * Fixed various GCC compiler warnings. +* Unmask SError and Debug exceptions in the trusted firmware. + Also route external abort and SError interrupts to EL3. + ARM Trusted Firmware - version 0.2 ================================== diff --git a/docs/user-guide.md b/docs/user-guide.md index debda445a..45e850b22 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -661,7 +661,9 @@ BL1 performs minimal architectural initialization as follows. - `SCR`. Use of the HVC instruction from EL1 is enabled by setting the `SCR.HCE` bit. FIQ exceptions are configured to be taken in EL3 by setting the `SCR.FIQ` bit. The register width of the next lower - exception level is set to AArch64 by setting the `SCR.RW` bit. + exception level is set to AArch64 by setting the `SCR.RW` bit. External + Aborts and SError Interrupts are configured to be taken in EL3 by + setting the `SCR.EA` bit. - `CPTR_EL3`. Accesses to the `CPACR` from EL1 or EL2, or the `CPTR_EL2` from EL2 are configured to not trap to EL3 by clearing the diff --git a/include/aarch64/arch_helpers.h b/include/aarch64/arch_helpers.h index 348d5452d..b571a5db6 100644 --- a/include/aarch64/arch_helpers.h +++ b/include/aarch64/arch_helpers.h @@ -80,10 +80,12 @@ extern void dcsw_op_all(unsigned int); extern void enable_irq(void); extern void enable_fiq(void); extern void enable_serror(void); +extern void enable_debug_exceptions(void); extern void disable_irq(void); extern void disable_fiq(void); extern void disable_serror(void); +extern void disable_debug_exceptions(void); extern unsigned long read_id_pfr1_el1(void); extern unsigned long read_id_aa64pfr0_el1(void); diff --git a/lib/arch/aarch64/misc_helpers.S b/lib/arch/aarch64/misc_helpers.S index 8c1f74000..05e90f952 100644 --- a/lib/arch/aarch64/misc_helpers.S +++ b/lib/arch/aarch64/misc_helpers.S @@ -39,6 +39,9 @@ .globl enable_serror .globl disable_serror + .globl enable_debug_exceptions + .globl disable_debug_exceptions + .globl read_daif .globl write_daif @@ -110,6 +113,11 @@ enable_serror:; .type enable_serror, %function ret +enable_debug_exceptions: + msr daifclr, #DAIF_DBG_BIT + ret + + disable_irq:; .type disable_irq, %function msr daifset, #DAIF_IRQ_BIT ret @@ -125,6 +133,11 @@ disable_serror:; .type disable_serror, %function ret +disable_debug_exceptions: + msr daifset, #DAIF_DBG_BIT + ret + + read_daif:; .type read_daif, %function mrs x0, daif ret