summaryrefslogtreecommitdiffstats
path: root/ArmPkg/Drivers/CpuDxe
diff options
context:
space:
mode:
authorHeyi Guo <heyi.guo@linaro.org>2015-09-24 17:05:39 +0000
committerabiesheuvel <abiesheuvel@Edk2>2015-09-24 17:05:39 +0000
commit36c64c664ba18026aad5375dbb80118bd3141266 (patch)
tree5903939dcfd0294fa2b2d31aa31428e35b320405 /ArmPkg/Drivers/CpuDxe
parentbe73a0c4839f93de43b4db64f874cfe61a55acc0 (diff)
downloadedk2-36c64c664ba18026aad5375dbb80118bd3141266.tar.gz
edk2-36c64c664ba18026aad5375dbb80118bd3141266.tar.bz2
edk2-36c64c664ba18026aad5375dbb80118bd3141266.zip
ArmPkg/CpuDxe: Disable interrupt before restoring context
Interrupt must be disabled before we storing ELR and other system registers, or else ELR will be overridden by interrupt reentrance. This bug is critical as we may get occasional exception or dead loop when interrupt reentrance occurs: After increasing SP ... Before popping out registers Or After restoring ELR The 1st circumstance could also be resolved by optimizing SP operation (Pop out registers before adding SP back), but the 2nd could not be resolved by disabling interrupt. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Heyi Guo <heyi.guo@linaro.org> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18538 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'ArmPkg/Drivers/CpuDxe')
-rw-r--r--ArmPkg/Drivers/CpuDxe/AArch64/ExceptionSupport.S8
1 files changed, 8 insertions, 0 deletions
diff --git a/ArmPkg/Drivers/CpuDxe/AArch64/ExceptionSupport.S b/ArmPkg/Drivers/CpuDxe/AArch64/ExceptionSupport.S
index 2682f4fe75..ca6c9a1522 100644
--- a/ArmPkg/Drivers/CpuDxe/AArch64/ExceptionSupport.S
+++ b/ArmPkg/Drivers/CpuDxe/AArch64/ExceptionSupport.S
@@ -358,6 +358,14 @@ ASM_PFX(AsmCommonExceptionEntry):
#define REG_PAIR(REG1, REG2, OFFSET, CONTEXT_SIZE) ldp REG1, REG2, [sp, #(OFFSET-CONTEXT_SIZE)]
#define REG_ONE(REG1, OFFSET, CONTEXT_SIZE) ldur REG1, [sp, #(OFFSET-CONTEXT_SIZE)]
+ //
+ // Disable interrupt(IRQ and FIQ) before restoring context,
+ // or else the context will be corrupted by interrupt reentrance.
+ // Interrupt mask will be restored from spsr by hardware when we call eret
+ //
+ msr daifset, #3
+ isb
+
// Adjust SP to pop system registers
add sp, sp, #(GP_CONTEXT_SIZE + FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)
ALL_SYS_REGS