diff options
author | Dimitris Papastamos <dimitris.papastamos@arm.com> | 2017-12-18 13:46:21 +0000 |
---|---|---|
committer | Dimitris Papastamos <dimitris.papastamos@arm.com> | 2018-01-11 10:26:15 +0000 |
commit | a1781a211a53df6a24345d774c0f2eaa5b675ca8 (patch) | |
tree | 134af9ccff89ab1d2ddac0624d80bb1c18349646 /include/lib | |
parent | f62ad322695d16178db464dc062fe0af592c6780 (diff) |
Workaround for CVE-2017-5715 on Cortex A73 and A75
Invalidate the Branch Target Buffer (BTB) on entry to EL3 by
temporarily dropping into AArch32 Secure-EL1 and executing the
`BPIALL` instruction.
This is achieved by using 3 vector tables. There is the runtime
vector table which is used to handle exceptions and 2 additional
tables which are required to implement this workaround. The
additional tables are `vbar0` and `vbar1`.
The sequence of events for handling a single exception is
as follows:
1) Install vector table `vbar0` which saves the CPU context on entry
to EL3 and sets up the Secure-EL1 context to execute in AArch32 mode
with the MMU disabled and I$ enabled. This is the default vector table.
2) Before doing an ERET into Secure-EL1, switch vbar to point to
another vector table `vbar1`. This is required to restore EL3 state
when returning from the workaround, before proceeding with normal EL3
exception handling.
3) While in Secure-EL1, the `BPIALL` instruction is executed and an
SMC call back to EL3 is performed.
4) On entry to EL3 from Secure-EL1, the saved context from step 1) is
restored. The vbar is switched to point to `vbar0` in preparation to
handle further exceptions. Finally a branch to the runtime vector
table entry is taken to complete the handling of the original
exception.
This workaround is enabled by default on the affected CPUs.
NOTE
====
There are 4 different stubs in Secure-EL1. Each stub corresponds to
an exception type such as Sync/IRQ/FIQ/SError. Each stub will move a
different value in `R0` before doing an SMC call back into EL3.
Without this piece of information it would not be possible to know
what the original exception type was as we cannot use `ESR_EL3` to
distinguish between IRQs and FIQs.
Change-Id: I90b32d14a3735290b48685d43c70c99daaa4b434
Signed-off-by: Dimitris Papastamos <dimitris.papastamos@arm.com>
Diffstat (limited to 'include/lib')
-rw-r--r-- | include/lib/aarch64/arch.h | 5 | ||||
-rw-r--r-- | include/lib/el3_runtime/aarch64/context.h | 26 |
2 files changed, 30 insertions, 1 deletions
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h index 96e2d5fe..13a8c797 100644 --- a/include/lib/aarch64/arch.h +++ b/include/lib/aarch64/arch.h @@ -337,6 +337,11 @@ #define SPSR_T_ARM U(0x0) #define SPSR_T_THUMB U(0x1) +#define SPSR_M_SHIFT U(4) +#define SPSR_M_MASK U(0x1) +#define SPSR_M_AARCH64 U(0x0) +#define SPSR_M_AARCH32 U(0x1) + #define DISABLE_ALL_EXCEPTIONS \ (DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT | DAIF_DBG_BIT) diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h index 58899049..5e212ec3 100644 --- a/include/lib/el3_runtime/aarch64/context.h +++ b/include/lib/el3_runtime/aarch64/context.h @@ -46,12 +46,26 @@ #define CTX_GPREG_SP_EL0 U(0xf8) #define CTX_GPREGS_END U(0x100) +#if WORKAROUND_CVE_2017_5715 +#define CTX_CVE_2017_5715_OFFSET (CTX_GPREGS_OFFSET + CTX_GPREGS_END) +#define CTX_CVE_2017_5715_QUAD0 U(0x0) +#define CTX_CVE_2017_5715_QUAD1 U(0x8) +#define CTX_CVE_2017_5715_QUAD2 U(0x10) +#define CTX_CVE_2017_5715_QUAD3 U(0x18) +#define CTX_CVE_2017_5715_QUAD4 U(0x20) +#define CTX_CVE_2017_5715_QUAD5 U(0x28) +#define CTX_CVE_2017_5715_END U(0x30) +#else +#define CTX_CVE_2017_5715_OFFSET CTX_GPREGS_OFFSET +#define CTX_CVE_2017_5715_END CTX_GPREGS_END +#endif + /******************************************************************************* * Constants that allow assembler code to access members of and the 'el3_state' * structure at their correct offsets. Note that some of the registers are only * 32-bits wide but are stored as 64-bit values for convenience ******************************************************************************/ -#define CTX_EL3STATE_OFFSET (CTX_GPREGS_OFFSET + CTX_GPREGS_END) +#define CTX_EL3STATE_OFFSET (CTX_CVE_2017_5715_OFFSET + CTX_CVE_2017_5715_END) #define CTX_SCR_EL3 U(0x0) #define CTX_RUNTIME_SP U(0x8) #define CTX_SPSR_EL3 U(0x10) @@ -186,6 +200,9 @@ /* Constants to determine the size of individual context structures */ #define CTX_GPREG_ALL (CTX_GPREGS_END >> DWORD_SHIFT) +#if WORKAROUND_CVE_2017_5715 +#define CTX_CVE_2017_5715_ALL (CTX_CVE_2017_5715_END >> DWORD_SHIFT) +#endif #define CTX_SYSREG_ALL (CTX_SYSREGS_END >> DWORD_SHIFT) #if CTX_INCLUDE_FPREGS #define CTX_FPREG_ALL (CTX_FPREGS_END >> DWORD_SHIFT) @@ -201,6 +218,10 @@ */ DEFINE_REG_STRUCT(gp_regs, CTX_GPREG_ALL); +#if WORKAROUND_CVE_2017_5715 +DEFINE_REG_STRUCT(cve_2017_5715_regs, CTX_CVE_2017_5715_ALL); +#endif + /* * AArch64 EL1 system register context structure for preserving the * architectural state during switches from one security state to @@ -242,6 +263,9 @@ DEFINE_REG_STRUCT(el3_state, CTX_EL3STATE_ALL); */ typedef struct cpu_context { gp_regs_t gpregs_ctx; +#if WORKAROUND_CVE_2017_5715 + cve_2017_5715_regs_t cve_2017_5715_regs_ctx; +#endif el3_state_t el3state_ctx; el1_sys_regs_t sysregs_ctx; #if CTX_INCLUDE_FPREGS |