ArmPkg: CpuDxe: fix AArch64 interrupt read masks

The AArch64 DAIF bits are different for reading (mrs) versus writing
(msr). The bitmask definitions assumed they were the same causing
incorrect results when trying to determine the current interrupt
state through ArmGetInterruptState.

The logic for interpreting the DAIF read data using the csel instruction
was also incorrect and is fixed.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Eugene Cohen <eugene@hp.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
This commit is contained in:
Cohen, Eugene 2016-02-22 23:08:27 +00:00 committed by Ard Biesheuvel
parent 2ba36b2f0e
commit 4af3dd80ab
2 changed files with 23 additions and 25 deletions

View File

@ -35,12 +35,14 @@ GCC_ASM_EXPORT (ReadCLIDR)
.set MPIDR_U_BIT, (30) .set MPIDR_U_BIT, (30)
.set MPIDR_U_MASK, (1 << MPIDR_U_BIT) .set MPIDR_U_MASK, (1 << MPIDR_U_BIT)
.set DAIF_FIQ_BIT, (1 << 0)
.set DAIF_IRQ_BIT, (1 << 1) // DAIF bit definitions for writing through msr daifclr/sr daifset
.set DAIF_ABORT_BIT, (1 << 2) .set DAIF_WR_FIQ_BIT, (1 << 0)
.set DAIF_DEBUG_BIT, (1 << 3) .set DAIF_WR_IRQ_BIT, (1 << 1)
.set DAIF_INT_BITS, (DAIF_FIQ_BIT | DAIF_IRQ_BIT) .set DAIF_WR_ABORT_BIT, (1 << 2)
.set DAIF_ALL, (DAIF_DEBUG_BIT | DAIF_ABORT_BIT | DAIF_INT_BITS) .set DAIF_WR_DEBUG_BIT, (1 << 3)
.set DAIF_WR_INT_BITS, (DAIF_WR_FIQ_BIT | DAIF_WR_IRQ_BIT)
.set DAIF_WR_ALL, (DAIF_WR_DEBUG_BIT | DAIF_WR_ABORT_BIT | DAIF_WR_INT_BITS)
ASM_PFX(ArmIsMpCore): ASM_PFX(ArmIsMpCore):
@ -52,55 +54,55 @@ ASM_PFX(ArmIsMpCore):
ASM_PFX(ArmEnableAsynchronousAbort): ASM_PFX(ArmEnableAsynchronousAbort):
msr daifclr, #DAIF_ABORT_BIT msr daifclr, #DAIF_WR_ABORT_BIT
isb isb
ret ret
ASM_PFX(ArmDisableAsynchronousAbort): ASM_PFX(ArmDisableAsynchronousAbort):
msr daifset, #DAIF_ABORT_BIT msr daifset, #DAIF_WR_ABORT_BIT
isb isb
ret ret
ASM_PFX(ArmEnableIrq): ASM_PFX(ArmEnableIrq):
msr daifclr, #DAIF_IRQ_BIT msr daifclr, #DAIF_WR_IRQ_BIT
isb isb
ret ret
ASM_PFX(ArmDisableIrq): ASM_PFX(ArmDisableIrq):
msr daifset, #DAIF_IRQ_BIT msr daifset, #DAIF_WR_IRQ_BIT
isb isb
ret ret
ASM_PFX(ArmEnableFiq): ASM_PFX(ArmEnableFiq):
msr daifclr, #DAIF_FIQ_BIT msr daifclr, #DAIF_WR_FIQ_BIT
isb isb
ret ret
ASM_PFX(ArmDisableFiq): ASM_PFX(ArmDisableFiq):
msr daifset, #DAIF_FIQ_BIT msr daifset, #DAIF_WR_FIQ_BIT
isb isb
ret ret
ASM_PFX(ArmEnableInterrupts): ASM_PFX(ArmEnableInterrupts):
msr daifclr, #DAIF_INT_BITS msr daifclr, #DAIF_WR_INT_BITS
isb isb
ret ret
ASM_PFX(ArmDisableInterrupts): ASM_PFX(ArmDisableInterrupts):
msr daifset, #DAIF_INT_BITS msr daifset, #DAIF_WR_INT_BITS
isb isb
ret ret
ASM_PFX(ArmDisableAllExceptions): ASM_PFX(ArmDisableAllExceptions):
msr daifset, #DAIF_ALL msr daifset, #DAIF_WR_ALL
isb isb
ret ret

View File

@ -42,8 +42,8 @@ GCC_ASM_EXPORT (ArmWriteCpuActlr)
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
.set DAIF_FIQ_BIT, (1 << 0) .set DAIF_RD_FIQ_BIT, (1 << 6)
.set DAIF_IRQ_BIT, (1 << 1) .set DAIF_RD_IRQ_BIT, (1 << 7)
ASM_PFX(ArmReadMidr): ASM_PFX(ArmReadMidr):
mrs x0, midr_el1 // Read from Main ID Register (MIDR) mrs x0, midr_el1 // Read from Main ID Register (MIDR)
@ -55,18 +55,14 @@ ASM_PFX(ArmCacheInfo):
ASM_PFX(ArmGetInterruptState): ASM_PFX(ArmGetInterruptState):
mrs x0, daif mrs x0, daif
tst w0, #DAIF_IRQ_BIT // Check if IRQ is enabled. Enabled if 0. tst w0, #DAIF_RD_IRQ_BIT // Check if IRQ is enabled. Enabled if 0 (Z=1)
mov w0, #0 cset w0, eq // if Z=1 return 1, else 0
mov w1, #1
csel w0, w1, w0, ne
ret ret
ASM_PFX(ArmGetFiqState): ASM_PFX(ArmGetFiqState):
mrs x0, daif mrs x0, daif
tst w0, #DAIF_FIQ_BIT // Check if FIQ is enabled. Enabled if 0. tst w0, #DAIF_RD_FIQ_BIT // Check if FIQ is enabled. Enabled if 0 (Z=1)
mov w0, #0 cset w0, eq // if Z=1 return 1, else 0
mov w1, #1
csel w0, w1, w0, ne
ret ret
ASM_PFX(ArmWriteCpacr): ASM_PFX(ArmWriteCpacr):