diff options
Diffstat (limited to 'roms/edk2/ArmPkg/Library/ArmLib/AArch64')
6 files changed, 1037 insertions, 0 deletions
diff --git a/roms/edk2/ArmPkg/Library/ArmLib/AArch64/AArch64ArchTimerSupport.S b/roms/edk2/ArmPkg/Library/ArmLib/AArch64/AArch64ArchTimerSupport.S new file mode 100644 index 000000000..574e0d593 --- /dev/null +++ b/roms/edk2/ArmPkg/Library/ArmLib/AArch64/AArch64ArchTimerSupport.S @@ -0,0 +1,113 @@ +#------------------------------------------------------------------------------
+#
+# Copyright (c) 2011 - 2013, ARM Limited. All rights reserved.
+# Copyright (c) 2016, Linaro Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#------------------------------------------------------------------------------
+
+#include <AsmMacroIoLibV8.h>
+
+ASM_FUNC(ArmReadCntFrq)
+ mrs x0, cntfrq_el0 // Read CNTFRQ
+ ret
+
+
+# NOTE - Can only write while at highest implemented EL level (EL3 on model). Else ReadOnly (EL2, EL1, EL0)
+ASM_FUNC(ArmWriteCntFrq)
+ msr cntfrq_el0, x0 // Write to CNTFRQ
+ ret
+
+
+ASM_FUNC(ArmReadCntPct)
+ mrs x0, cntpct_el0 // Read CNTPCT (Physical counter register)
+ ret
+
+
+ASM_FUNC(ArmReadCntkCtl)
+ mrs x0, cntkctl_el1 // Read CNTK_CTL (Timer PL1 Control Register)
+ ret
+
+
+ASM_FUNC(ArmWriteCntkCtl)
+ msr cntkctl_el1, x0 // Write to CNTK_CTL (Timer PL1 Control Register)
+ ret
+
+
+ASM_FUNC(ArmReadCntpTval)
+ mrs x0, cntp_tval_el0 // Read CNTP_TVAL (PL1 physical timer value register)
+ ret
+
+
+ASM_FUNC(ArmWriteCntpTval)
+ msr cntp_tval_el0, x0 // Write to CNTP_TVAL (PL1 physical timer value register)
+ ret
+
+
+ASM_FUNC(ArmReadCntpCtl)
+ mrs x0, cntp_ctl_el0 // Read CNTP_CTL (PL1 Physical Timer Control Register)
+ ret
+
+
+ASM_FUNC(ArmWriteCntpCtl)
+ msr cntp_ctl_el0, x0 // Write to CNTP_CTL (PL1 Physical Timer Control Register)
+ ret
+
+
+ASM_FUNC(ArmReadCntvTval)
+ mrs x0, cntv_tval_el0 // Read CNTV_TVAL (Virtual Timer Value register)
+ ret
+
+
+ASM_FUNC(ArmWriteCntvTval)
+ msr cntv_tval_el0, x0 // Write to CNTV_TVAL (Virtual Timer Value register)
+ ret
+
+
+ASM_FUNC(ArmReadCntvCtl)
+ mrs x0, cntv_ctl_el0 // Read CNTV_CTL (Virtual Timer Control Register)
+ ret
+
+
+ASM_FUNC(ArmWriteCntvCtl)
+ msr cntv_ctl_el0, x0 // Write to CNTV_CTL (Virtual Timer Control Register)
+ ret
+
+
+ASM_FUNC(ArmReadCntvCt)
+ mrs x0, cntvct_el0 // Read CNTVCT (Virtual Count Register)
+ ret
+
+
+ASM_FUNC(ArmReadCntpCval)
+ mrs x0, cntp_cval_el0 // Read CNTP_CTVAL (Physical Timer Compare Value Register)
+ ret
+
+
+ASM_FUNC(ArmWriteCntpCval)
+ msr cntp_cval_el0, x0 // Write to CNTP_CTVAL (Physical Timer Compare Value Register)
+ ret
+
+
+ASM_FUNC(ArmReadCntvCval)
+ mrs x0, cntv_cval_el0 // Read CNTV_CTVAL (Virtual Timer Compare Value Register)
+ ret
+
+
+ASM_FUNC(ArmWriteCntvCval)
+ msr cntv_cval_el0, x0 // write to CNTV_CTVAL (Virtual Timer Compare Value Register)
+ ret
+
+
+ASM_FUNC(ArmReadCntvOff)
+ mrs x0, cntvoff_el2 // Read CNTVOFF (virtual Offset register)
+ ret
+
+
+ASM_FUNC(ArmWriteCntvOff)
+ msr cntvoff_el2, x0 // Write to CNTVOFF (Virtual Offset register)
+ ret
+
+
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED
diff --git a/roms/edk2/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c b/roms/edk2/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c new file mode 100644 index 000000000..3fbd59119 --- /dev/null +++ b/roms/edk2/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c @@ -0,0 +1,73 @@ +/** @file
+
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+ Portions copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+
+#include <Library/ArmLib.h>
+#include <Library/DebugLib.h>
+
+#include <Chipset/AArch64.h>
+
+#include "AArch64Lib.h"
+#include "ArmLibPrivate.h"
+
+VOID
+AArch64DataCacheOperation (
+ IN AARCH64_CACHE_OPERATION DataCacheOperation
+ )
+{
+ UINTN SavedInterruptState;
+
+ SavedInterruptState = ArmGetInterruptState ();
+ ArmDisableInterrupts();
+
+ AArch64AllDataCachesOperation (DataCacheOperation);
+
+ ArmDataSynchronizationBarrier ();
+
+ if (SavedInterruptState) {
+ ArmEnableInterrupts ();
+ }
+}
+
+VOID
+EFIAPI
+ArmInvalidateDataCache (
+ VOID
+ )
+{
+ ASSERT (!ArmMmuEnabled ());
+
+ ArmDataSynchronizationBarrier ();
+ AArch64DataCacheOperation (ArmInvalidateDataCacheEntryBySetWay);
+}
+
+VOID
+EFIAPI
+ArmCleanInvalidateDataCache (
+ VOID
+ )
+{
+ ASSERT (!ArmMmuEnabled ());
+
+ ArmDataSynchronizationBarrier ();
+ AArch64DataCacheOperation (ArmCleanInvalidateDataCacheEntryBySetWay);
+}
+
+VOID
+EFIAPI
+ArmCleanDataCache (
+ VOID
+ )
+{
+ ASSERT (!ArmMmuEnabled ());
+
+ ArmDataSynchronizationBarrier ();
+ AArch64DataCacheOperation (ArmCleanDataCacheEntryBySetWay);
+}
diff --git a/roms/edk2/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h b/roms/edk2/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h new file mode 100644 index 000000000..b2c8a8ea0 --- /dev/null +++ b/roms/edk2/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.h @@ -0,0 +1,39 @@ +/** @file
+
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+ Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __AARCH64_LIB_H__
+#define __AARCH64_LIB_H__
+
+typedef VOID (*AARCH64_CACHE_OPERATION)(UINTN);
+
+VOID
+AArch64AllDataCachesOperation (
+ IN AARCH64_CACHE_OPERATION DataCacheOperation
+ );
+
+VOID
+EFIAPI
+ArmInvalidateDataCacheEntryBySetWay (
+ IN UINTN SetWayFormat
+ );
+
+VOID
+EFIAPI
+ArmCleanDataCacheEntryBySetWay (
+ IN UINTN SetWayFormat
+ );
+
+VOID
+EFIAPI
+ArmCleanInvalidateDataCacheEntryBySetWay (
+ IN UINTN SetWayFormat
+ );
+
+#endif // __AARCH64_LIB_H__
+
diff --git a/roms/edk2/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S b/roms/edk2/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S new file mode 100644 index 000000000..199374ff5 --- /dev/null +++ b/roms/edk2/ArmPkg/Library/ArmLib/AArch64/AArch64Support.S @@ -0,0 +1,489 @@ +#------------------------------------------------------------------------------
+#
+# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+# Copyright (c) 2011 - 2017, ARM Limited. All rights reserved.
+# Copyright (c) 2016, Linaro Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#------------------------------------------------------------------------------
+
+#include <Chipset/AArch64.h>
+#include <AsmMacroIoLibV8.h>
+
+.set CTRL_M_BIT, (1 << 0)
+.set CTRL_A_BIT, (1 << 1)
+.set CTRL_C_BIT, (1 << 2)
+.set CTRL_SA_BIT, (1 << 3)
+.set CTRL_I_BIT, (1 << 12)
+.set CTRL_V_BIT, (1 << 12)
+.set CPACR_VFP_BITS, (3 << 20)
+
+ASM_FUNC(ArmInvalidateDataCacheEntryByMVA)
+ dc ivac, x0 // Invalidate single data cache line
+ ret
+
+
+ASM_FUNC(ArmCleanDataCacheEntryByMVA)
+ dc cvac, x0 // Clean single data cache line
+ ret
+
+
+ASM_FUNC(ArmCleanDataCacheEntryToPoUByMVA)
+ dc cvau, x0 // Clean single data cache line to PoU
+ ret
+
+ASM_FUNC(ArmInvalidateInstructionCacheEntryToPoUByMVA)
+ ic ivau, x0 // Invalidate single instruction cache line to PoU
+ ret
+
+
+ASM_FUNC(ArmCleanInvalidateDataCacheEntryByMVA)
+ dc civac, x0 // Clean and invalidate single data cache line
+ ret
+
+
+ASM_FUNC(ArmInvalidateDataCacheEntryBySetWay)
+ dc isw, x0 // Invalidate this line
+ ret
+
+
+ASM_FUNC(ArmCleanInvalidateDataCacheEntryBySetWay)
+ dc cisw, x0 // Clean and Invalidate this line
+ ret
+
+
+ASM_FUNC(ArmCleanDataCacheEntryBySetWay)
+ dc csw, x0 // Clean this line
+ ret
+
+
+ASM_FUNC(ArmInvalidateInstructionCache)
+ ic iallu // Invalidate entire instruction cache
+ dsb sy
+ isb
+ ret
+
+
+ASM_FUNC(ArmEnableMmu)
+ EL1_OR_EL2_OR_EL3(x1)
+1: mrs x0, sctlr_el1 // Read System control register EL1
+ b 4f
+2: mrs x0, sctlr_el2 // Read System control register EL2
+ b 4f
+3: mrs x0, sctlr_el3 // Read System control register EL3
+4: orr x0, x0, #CTRL_M_BIT // Set MMU enable bit
+ EL1_OR_EL2_OR_EL3(x1)
+1: tlbi vmalle1
+ dsb nsh
+ isb
+ msr sctlr_el1, x0 // Write back
+ b 4f
+2: tlbi alle2
+ dsb nsh
+ isb
+ msr sctlr_el2, x0 // Write back
+ b 4f
+3: tlbi alle3
+ dsb nsh
+ isb
+ msr sctlr_el3, x0 // Write back
+4: isb
+ ret
+
+
+ASM_FUNC(ArmDisableMmu)
+ EL1_OR_EL2_OR_EL3(x1)
+1: mrs x0, sctlr_el1 // Read System Control Register EL1
+ b 4f
+2: mrs x0, sctlr_el2 // Read System Control Register EL2
+ b 4f
+3: mrs x0, sctlr_el3 // Read System Control Register EL3
+4: and x0, x0, #~CTRL_M_BIT // Clear MMU enable bit
+ EL1_OR_EL2_OR_EL3(x1)
+1: msr sctlr_el1, x0 // Write back
+ tlbi vmalle1
+ b 4f
+2: msr sctlr_el2, x0 // Write back
+ tlbi alle2
+ b 4f
+3: msr sctlr_el3, x0 // Write back
+ tlbi alle3
+4: dsb sy
+ isb
+ ret
+
+
+ASM_FUNC(ArmDisableCachesAndMmu)
+ EL1_OR_EL2_OR_EL3(x1)
+1: mrs x0, sctlr_el1 // Get control register EL1
+ b 4f
+2: mrs x0, sctlr_el2 // Get control register EL2
+ b 4f
+3: mrs x0, sctlr_el3 // Get control register EL3
+4: mov x1, #~(CTRL_M_BIT | CTRL_C_BIT | CTRL_I_BIT) // Disable MMU, D & I caches
+ and x0, x0, x1
+ EL1_OR_EL2_OR_EL3(x1)
+1: msr sctlr_el1, x0 // Write back control register
+ b 4f
+2: msr sctlr_el2, x0 // Write back control register
+ b 4f
+3: msr sctlr_el3, x0 // Write back control register
+4: dsb sy
+ isb
+ ret
+
+
+ASM_FUNC(ArmMmuEnabled)
+ EL1_OR_EL2_OR_EL3(x1)
+1: mrs x0, sctlr_el1 // Get control register EL1
+ b 4f
+2: mrs x0, sctlr_el2 // Get control register EL2
+ b 4f
+3: mrs x0, sctlr_el3 // Get control register EL3
+4: and x0, x0, #CTRL_M_BIT
+ ret
+
+
+ASM_FUNC(ArmEnableDataCache)
+ EL1_OR_EL2_OR_EL3(x1)
+1: mrs x0, sctlr_el1 // Get control register EL1
+ b 4f
+2: mrs x0, sctlr_el2 // Get control register EL2
+ b 4f
+3: mrs x0, sctlr_el3 // Get control register EL3
+4: orr x0, x0, #CTRL_C_BIT // Set C bit
+ EL1_OR_EL2_OR_EL3(x1)
+1: msr sctlr_el1, x0 // Write back control register
+ b 4f
+2: msr sctlr_el2, x0 // Write back control register
+ b 4f
+3: msr sctlr_el3, x0 // Write back control register
+4: dsb sy
+ isb
+ ret
+
+
+ASM_FUNC(ArmDisableDataCache)
+ EL1_OR_EL2_OR_EL3(x1)
+1: mrs x0, sctlr_el1 // Get control register EL1
+ b 4f
+2: mrs x0, sctlr_el2 // Get control register EL2
+ b 4f
+3: mrs x0, sctlr_el3 // Get control register EL3
+4: and x0, x0, #~CTRL_C_BIT // Clear C bit
+ EL1_OR_EL2_OR_EL3(x1)
+1: msr sctlr_el1, x0 // Write back control register
+ b 4f
+2: msr sctlr_el2, x0 // Write back control register
+ b 4f
+3: msr sctlr_el3, x0 // Write back control register
+4: dsb sy
+ isb
+ ret
+
+
+ASM_FUNC(ArmEnableInstructionCache)
+ EL1_OR_EL2_OR_EL3(x1)
+1: mrs x0, sctlr_el1 // Get control register EL1
+ b 4f
+2: mrs x0, sctlr_el2 // Get control register EL2
+ b 4f
+3: mrs x0, sctlr_el3 // Get control register EL3
+4: orr x0, x0, #CTRL_I_BIT // Set I bit
+ EL1_OR_EL2_OR_EL3(x1)
+1: msr sctlr_el1, x0 // Write back control register
+ b 4f
+2: msr sctlr_el2, x0 // Write back control register
+ b 4f
+3: msr sctlr_el3, x0 // Write back control register
+4: dsb sy
+ isb
+ ret
+
+
+ASM_FUNC(ArmDisableInstructionCache)
+ EL1_OR_EL2_OR_EL3(x1)
+1: mrs x0, sctlr_el1 // Get control register EL1
+ b 4f
+2: mrs x0, sctlr_el2 // Get control register EL2
+ b 4f
+3: mrs x0, sctlr_el3 // Get control register EL3
+4: and x0, x0, #~CTRL_I_BIT // Clear I bit
+ EL1_OR_EL2_OR_EL3(x1)
+1: msr sctlr_el1, x0 // Write back control register
+ b 4f
+2: msr sctlr_el2, x0 // Write back control register
+ b 4f
+3: msr sctlr_el3, x0 // Write back control register
+4: dsb sy
+ isb
+ ret
+
+
+ASM_FUNC(ArmEnableAlignmentCheck)
+ EL1_OR_EL2(x1)
+1: mrs x0, sctlr_el1 // Get control register EL1
+ b 3f
+2: mrs x0, sctlr_el2 // Get control register EL2
+3: orr x0, x0, #CTRL_A_BIT // Set A (alignment check) bit
+ EL1_OR_EL2(x1)
+1: msr sctlr_el1, x0 // Write back control register
+ b 3f
+2: msr sctlr_el2, x0 // Write back control register
+3: dsb sy
+ isb
+ ret
+
+
+ASM_FUNC(ArmDisableAlignmentCheck)
+ EL1_OR_EL2_OR_EL3(x1)
+1: mrs x0, sctlr_el1 // Get control register EL1
+ b 4f
+2: mrs x0, sctlr_el2 // Get control register EL2
+ b 4f
+3: mrs x0, sctlr_el3 // Get control register EL3
+4: and x0, x0, #~CTRL_A_BIT // Clear A (alignment check) bit
+ EL1_OR_EL2_OR_EL3(x1)
+1: msr sctlr_el1, x0 // Write back control register
+ b 4f
+2: msr sctlr_el2, x0 // Write back control register
+ b 4f
+3: msr sctlr_el3, x0 // Write back control register
+4: dsb sy
+ isb
+ ret
+
+ASM_FUNC(ArmEnableStackAlignmentCheck)
+ EL1_OR_EL2(x1)
+1: mrs x0, sctlr_el1 // Get control register EL1
+ b 3f
+2: mrs x0, sctlr_el2 // Get control register EL2
+3: orr x0, x0, #CTRL_SA_BIT // Set SA (stack alignment check) bit
+ EL1_OR_EL2(x1)
+1: msr sctlr_el1, x0 // Write back control register
+ b 3f
+2: msr sctlr_el2, x0 // Write back control register
+3: dsb sy
+ isb
+ ret
+
+
+ASM_FUNC(ArmDisableStackAlignmentCheck)
+ EL1_OR_EL2_OR_EL3(x1)
+1: mrs x0, sctlr_el1 // Get control register EL1
+ b 4f
+2: mrs x0, sctlr_el2 // Get control register EL2
+ b 4f
+3: mrs x0, sctlr_el3 // Get control register EL3
+4: bic x0, x0, #CTRL_SA_BIT // Clear SA (stack alignment check) bit
+ EL1_OR_EL2_OR_EL3(x1)
+1: msr sctlr_el1, x0 // Write back control register
+ b 4f
+2: msr sctlr_el2, x0 // Write back control register
+ b 4f
+3: msr sctlr_el3, x0 // Write back control register
+4: dsb sy
+ isb
+ ret
+
+
+// Always turned on in AArch64. Else implementation specific. Leave in for C compatibility for now
+ASM_FUNC(ArmEnableBranchPrediction)
+ ret
+
+
+// Always turned on in AArch64. Else implementation specific. Leave in for C compatibility for now.
+ASM_FUNC(ArmDisableBranchPrediction)
+ ret
+
+
+ASM_FUNC(AArch64AllDataCachesOperation)
+// We can use regs 0-7 and 9-15 without having to save/restore.
+// Save our link register on the stack. - The stack must always be quad-word aligned
+ stp x29, x30, [sp, #-16]!
+ mov x29, sp
+ mov x1, x0 // Save Function call in x1
+ mrs x6, clidr_el1 // Read EL1 CLIDR
+ and x3, x6, #0x7000000 // Mask out all but Level of Coherency (LoC)
+ lsr x3, x3, #23 // Left align cache level value - the level is shifted by 1 to the
+ // right to ease the access to CSSELR and the Set/Way operation.
+ cbz x3, L_Finished // No need to clean if LoC is 0
+ mov x10, #0 // Start clean at cache level 0
+
+Loop1:
+ add x2, x10, x10, lsr #1 // Work out 3x cachelevel for cache info
+ lsr x12, x6, x2 // bottom 3 bits are the Cache type for this level
+ and x12, x12, #7 // get those 3 bits alone
+ cmp x12, #2 // what cache at this level?
+ b.lt L_Skip // no cache or only instruction cache at this level
+ msr csselr_el1, x10 // write the Cache Size selection register with current level (CSSELR)
+ isb // isb to sync the change to the CacheSizeID reg
+ mrs x12, ccsidr_el1 // reads current Cache Size ID register (CCSIDR)
+ and x2, x12, #0x7 // extract the line length field
+ add x2, x2, #4 // add 4 for the line length offset (log2 16 bytes)
+ mov x4, #0x400
+ sub x4, x4, #1
+ and x4, x4, x12, lsr #3 // x4 is the max number on the way size (right aligned)
+ clz w5, w4 // w5 is the bit position of the way size increment
+ mov x7, #0x00008000
+ sub x7, x7, #1
+ and x7, x7, x12, lsr #13 // x7 is the max number of the index size (right aligned)
+
+Loop2:
+ mov x9, x4 // x9 working copy of the max way size (right aligned)
+
+Loop3:
+ lsl x11, x9, x5
+ orr x0, x10, x11 // factor in the way number and cache number
+ lsl x11, x7, x2
+ orr x0, x0, x11 // factor in the index number
+
+ blr x1 // Goto requested cache operation
+
+ subs x9, x9, #1 // decrement the way number
+ b.ge Loop3
+ subs x7, x7, #1 // decrement the index
+ b.ge Loop2
+L_Skip:
+ add x10, x10, #2 // increment the cache number
+ cmp x3, x10
+ b.gt Loop1
+
+L_Finished:
+ dsb sy
+ isb
+ ldp x29, x30, [sp], #0x10
+ ret
+
+
+ASM_FUNC(ArmDataMemoryBarrier)
+ dmb sy
+ ret
+
+
+ASM_FUNC(ArmDataSynchronizationBarrier)
+ dsb sy
+ ret
+
+
+ASM_FUNC(ArmInstructionSynchronizationBarrier)
+ isb
+ ret
+
+
+ASM_FUNC(ArmWriteVBar)
+ EL1_OR_EL2_OR_EL3(x1)
+1: msr vbar_el1, x0 // Set the Address of the EL1 Vector Table in the VBAR register
+ b 4f
+2: msr vbar_el2, x0 // Set the Address of the EL2 Vector Table in the VBAR register
+ b 4f
+3: msr vbar_el3, x0 // Set the Address of the EL3 Vector Table in the VBAR register
+4: isb
+ ret
+
+ASM_FUNC(ArmReadVBar)
+ EL1_OR_EL2_OR_EL3(x1)
+1: mrs x0, vbar_el1 // Set the Address of the EL1 Vector Table in the VBAR register
+ ret
+2: mrs x0, vbar_el2 // Set the Address of the EL2 Vector Table in the VBAR register
+ ret
+3: mrs x0, vbar_el3 // Set the Address of the EL3 Vector Table in the VBAR register
+ ret
+
+
+ASM_FUNC(ArmEnableVFP)
+ // Check whether floating-point is implemented in the processor.
+ mov x1, x30 // Save LR
+ bl ArmReadIdPfr0 // Read EL1 Processor Feature Register (PFR0)
+ mov x30, x1 // Restore LR
+ ubfx x0, x0, #16, #4 // Extract the FP bits 16:19
+ cmp x0, #0xF // Check if FP bits are '1111b',
+ // i.e. Floating Point not implemented
+ b.eq 4f // Exit when VFP is not implemented.
+
+ // FVP is implemented.
+ // Make sure VFP exceptions are not trapped (to any exception level).
+ mrs x0, cpacr_el1 // Read EL1 Coprocessor Access Control Register (CPACR)
+ orr x0, x0, #CPACR_VFP_BITS // Disable FVP traps to EL1
+ msr cpacr_el1, x0 // Write back EL1 Coprocessor Access Control Register (CPACR)
+ mov x1, #AARCH64_CPTR_TFP // TFP Bit for trapping VFP Exceptions
+ EL1_OR_EL2_OR_EL3(x2)
+1:ret // Not configurable in EL1
+2:mrs x0, cptr_el2 // Disable VFP traps to EL2
+ bic x0, x0, x1
+ msr cptr_el2, x0
+ ret
+3:mrs x0, cptr_el3 // Disable VFP traps to EL3
+ bic x0, x0, x1
+ msr cptr_el3, x0
+4:ret
+
+
+ASM_FUNC(ArmCallWFI)
+ wfi
+ ret
+
+
+ASM_FUNC(ArmReadMpidr)
+ mrs x0, mpidr_el1 // read EL1 MPIDR
+ ret
+
+
+// Keep old function names for C compatibility for now. Change later?
+ASM_FUNC(ArmReadTpidrurw)
+ mrs x0, tpidr_el0 // read tpidr_el0 (v7 TPIDRURW) -> (v8 TPIDR_EL0)
+ ret
+
+
+// Keep old function names for C compatibility for now. Change later?
+ASM_FUNC(ArmWriteTpidrurw)
+ msr tpidr_el0, x0 // write tpidr_el0 (v7 TPIDRURW) -> (v8 TPIDR_EL0)
+ ret
+
+
+// Arch timers are mandatory on AArch64
+ASM_FUNC(ArmIsArchTimerImplemented)
+ mov x0, #1
+ ret
+
+
+ASM_FUNC(ArmReadIdPfr0)
+ mrs x0, id_aa64pfr0_el1 // Read ID_AA64PFR0 Register
+ ret
+
+
+// Q: id_aa64pfr1_el1 not defined yet. What does this function want to access?
+// A: used to setup arch timer. Check if we have security extensions, permissions to set stuff.
+// See: ArmPkg/Library/ArmArchTimerLib/AArch64/ArmArchTimerLib.c
+// Not defined yet, but stick in here for now, should read all zeros.
+ASM_FUNC(ArmReadIdPfr1)
+ mrs x0, id_aa64pfr1_el1 // Read ID_PFR1 Register
+ ret
+
+// VOID ArmWriteHcr(UINTN Hcr)
+ASM_FUNC(ArmWriteHcr)
+ msr hcr_el2, x0 // Write the passed HCR value
+ ret
+
+// UINTN ArmReadHcr(VOID)
+ASM_FUNC(ArmReadHcr)
+ mrs x0, hcr_el2
+ ret
+
+// UINTN ArmReadCurrentEL(VOID)
+ASM_FUNC(ArmReadCurrentEL)
+ mrs x0, CurrentEL
+ ret
+
+// UINT32 ArmReadCntHctl(VOID)
+ASM_FUNC(ArmReadCntHctl)
+ mrs x0, cnthctl_el2
+ ret
+
+// VOID ArmWriteCntHctl(UINT32 CntHctl)
+ASM_FUNC(ArmWriteCntHctl)
+ msr cnthctl_el2, x0
+ ret
+
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED
diff --git a/roms/edk2/ArmPkg/Library/ArmLib/AArch64/ArmLibSupport.S b/roms/edk2/ArmPkg/Library/ArmLib/AArch64/ArmLibSupport.S new file mode 100644 index 000000000..ba0ec5682 --- /dev/null +++ b/roms/edk2/ArmPkg/Library/ArmLib/AArch64/ArmLibSupport.S @@ -0,0 +1,217 @@ +#------------------------------------------------------------------------------
+#
+# Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+# Copyright (c) 2011 - 2016, ARM Limited. All rights reserved.
+# Copyright (c) 2016, Linaro Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#------------------------------------------------------------------------------
+
+#include <AsmMacroIoLibV8.h>
+
+.set DAIF_RD_FIQ_BIT, (1 << 6)
+.set DAIF_RD_IRQ_BIT, (1 << 7)
+
+.set SCTLR_ELx_M_BIT_POS, (0)
+
+ASM_FUNC(ArmReadMidr)
+ mrs x0, midr_el1 // Read from Main ID Register (MIDR)
+ ret
+
+ASM_FUNC(ArmCacheInfo)
+ mrs x0, ctr_el0 // Read from Cache Type Regiter (CTR)
+ ret
+
+ASM_FUNC(ArmGetInterruptState)
+ mrs x0, daif
+ tst w0, #DAIF_RD_IRQ_BIT // Check if IRQ is enabled. Enabled if 0 (Z=1)
+ cset w0, eq // if Z=1 return 1, else 0
+ ret
+
+ASM_FUNC(ArmGetFiqState)
+ mrs x0, daif
+ tst w0, #DAIF_RD_FIQ_BIT // Check if FIQ is enabled. Enabled if 0 (Z=1)
+ cset w0, eq // if Z=1 return 1, else 0
+ ret
+
+ASM_FUNC(ArmWriteCpacr)
+ msr cpacr_el1, x0 // Coprocessor Access Control Reg (CPACR)
+ ret
+
+ASM_FUNC(ArmWriteAuxCr)
+ EL1_OR_EL2(x1)
+1:msr actlr_el1, x0 // Aux Control Reg (ACTLR) at EL1. Also available in EL2 and EL3
+ ret
+2:msr actlr_el2, x0 // Aux Control Reg (ACTLR) at EL1. Also available in EL2 and EL3
+ ret
+
+ASM_FUNC(ArmReadAuxCr)
+ EL1_OR_EL2(x1)
+1:mrs x0, actlr_el1 // Aux Control Reg (ACTLR) at EL1. Also available in EL2 and EL3
+ ret
+2:mrs x0, actlr_el2 // Aux Control Reg (ACTLR) at EL1. Also available in EL2 and EL3
+ ret
+
+ASM_FUNC(ArmSetTTBR0)
+ EL1_OR_EL2_OR_EL3(x1)
+1:msr ttbr0_el1, x0 // Translation Table Base Reg 0 (TTBR0)
+ b 4f
+2:msr ttbr0_el2, x0 // Translation Table Base Reg 0 (TTBR0)
+ b 4f
+3:msr ttbr0_el3, x0 // Translation Table Base Reg 0 (TTBR0)
+4:isb
+ ret
+
+ASM_FUNC(ArmGetTTBR0BaseAddress)
+ EL1_OR_EL2(x1)
+1:mrs x0, ttbr0_el1
+ b 3f
+2:mrs x0, ttbr0_el2
+3:and x0, x0, 0xFFFFFFFFFFFF /* Look at bottom 48 bits */
+ isb
+ ret
+
+ASM_FUNC(ArmGetTCR)
+ EL1_OR_EL2_OR_EL3(x1)
+1:mrs x0, tcr_el1
+ b 4f
+2:mrs x0, tcr_el2
+ b 4f
+3:mrs x0, tcr_el3
+4:isb
+ ret
+
+ASM_FUNC(ArmSetTCR)
+ EL1_OR_EL2_OR_EL3(x1)
+1:msr tcr_el1, x0
+ b 4f
+2:msr tcr_el2, x0
+ b 4f
+3:msr tcr_el3, x0
+4:isb
+ ret
+
+ASM_FUNC(ArmGetMAIR)
+ EL1_OR_EL2_OR_EL3(x1)
+1:mrs x0, mair_el1
+ b 4f
+2:mrs x0, mair_el2
+ b 4f
+3:mrs x0, mair_el3
+4:isb
+ ret
+
+ASM_FUNC(ArmSetMAIR)
+ EL1_OR_EL2_OR_EL3(x1)
+1:msr mair_el1, x0
+ b 4f
+2:msr mair_el2, x0
+ b 4f
+3:msr mair_el3, x0
+4:isb
+ ret
+
+
+//
+//VOID
+//ArmUpdateTranslationTableEntry (
+// IN VOID *TranslationTableEntry // X0
+// IN VOID *MVA // X1
+// );
+ASM_FUNC(ArmUpdateTranslationTableEntry)
+ dsb nshst
+ lsr x1, x1, #12
+ EL1_OR_EL2_OR_EL3(x2)
+1: tlbi vaae1, x1 // TLB Invalidate VA , EL1
+ mrs x2, sctlr_el1
+ b 4f
+2: tlbi vae2, x1 // TLB Invalidate VA , EL2
+ mrs x2, sctlr_el2
+ b 4f
+3: tlbi vae3, x1 // TLB Invalidate VA , EL3
+ mrs x2, sctlr_el3
+4: tbnz x2, SCTLR_ELx_M_BIT_POS, 5f
+ dc ivac, x0 // invalidate in Dcache if MMU is still off
+5: dsb nsh
+ isb
+ ret
+
+ASM_FUNC(ArmInvalidateTlb)
+ EL1_OR_EL2_OR_EL3(x0)
+1: tlbi vmalle1
+ b 4f
+2: tlbi alle2
+ b 4f
+3: tlbi alle3
+4: dsb sy
+ isb
+ ret
+
+ASM_FUNC(ArmWriteCptr)
+ msr cptr_el3, x0 // EL3 Coprocessor Trap Reg (CPTR)
+ ret
+
+ASM_FUNC(ArmWriteScr)
+ msr scr_el3, x0 // Secure configuration register EL3
+ isb
+ ret
+
+ASM_FUNC(ArmWriteMVBar)
+ msr vbar_el3, x0 // Exception Vector Base address for Monitor on EL3
+ ret
+
+ASM_FUNC(ArmCallWFE)
+ wfe
+ ret
+
+ASM_FUNC(ArmCallSEV)
+ sev
+ ret
+
+ASM_FUNC(ArmReadCpuActlr)
+ mrs x0, S3_1_c15_c2_0
+ ret
+
+ASM_FUNC(ArmWriteCpuActlr)
+ msr S3_1_c15_c2_0, x0
+ dsb sy
+ isb
+ ret
+
+ASM_FUNC(ArmReadSctlr)
+ EL1_OR_EL2_OR_EL3(x1)
+1:mrs x0, sctlr_el1
+ ret
+2:mrs x0, sctlr_el2
+ ret
+3:mrs x0, sctlr_el3
+4:ret
+
+ASM_FUNC(ArmWriteSctlr)
+ EL1_OR_EL2_OR_EL3(x1)
+1:msr sctlr_el1, x0
+ ret
+2:msr sctlr_el2, x0
+ ret
+3:msr sctlr_el3, x0
+4:ret
+
+ASM_FUNC(ArmGetPhysicalAddressBits)
+ mrs x0, id_aa64mmfr0_el1
+ adr x1, .LPARanges
+ and x0, x0, #0xf
+ ldrb w0, [x1, x0]
+ ret
+
+//
+// Bits 0..3 of the AA64MFR0_EL1 system register encode the size of the
+// physical address space support on this CPU:
+// 0 == 32 bits, 1 == 36 bits, etc etc
+// 7 and up are reserved
+//
+.LPARanges:
+ .byte 32, 36, 40, 42, 44, 48, 52, 0
+ .byte 0, 0, 0, 0, 0, 0, 0, 0
+
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED
diff --git a/roms/edk2/ArmPkg/Library/ArmLib/AArch64/ArmLibSupportV8.S b/roms/edk2/ArmPkg/Library/ArmLib/AArch64/ArmLibSupportV8.S new file mode 100644 index 000000000..0e8d21e22 --- /dev/null +++ b/roms/edk2/ArmPkg/Library/ArmLib/AArch64/ArmLibSupportV8.S @@ -0,0 +1,106 @@ +#------------------------------------------------------------------------------
+#
+# Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+# Copyright (c) 2011 - 2014, ARM Limited. All rights reserved.
+# Copyright (c) 2016, Linaro Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#------------------------------------------------------------------------------
+
+#include <AsmMacroIoLibV8.h>
+
+.set MPIDR_U_BIT, (30)
+.set MPIDR_U_MASK, (1 << MPIDR_U_BIT)
+
+// DAIF bit definitions for writing through msr daifclr/sr daifset
+.set DAIF_WR_FIQ_BIT, (1 << 0)
+.set DAIF_WR_IRQ_BIT, (1 << 1)
+.set DAIF_WR_ABORT_BIT, (1 << 2)
+.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_FUNC(ArmIsMpCore)
+ mrs x0, mpidr_el1 // Read EL1 Multiprocessor Affinty Reg (MPIDR)
+ and x0, x0, #MPIDR_U_MASK // U Bit clear, the processor is part of a multiprocessor system
+ lsr x0, x0, #MPIDR_U_BIT
+ eor x0, x0, #1
+ ret
+
+
+ASM_FUNC(ArmEnableAsynchronousAbort)
+ msr daifclr, #DAIF_WR_ABORT_BIT
+ isb
+ ret
+
+
+ASM_FUNC(ArmDisableAsynchronousAbort)
+ msr daifset, #DAIF_WR_ABORT_BIT
+ isb
+ ret
+
+
+ASM_FUNC(ArmEnableIrq)
+ msr daifclr, #DAIF_WR_IRQ_BIT
+ isb
+ ret
+
+
+ASM_FUNC(ArmDisableIrq)
+ msr daifset, #DAIF_WR_IRQ_BIT
+ isb
+ ret
+
+
+ASM_FUNC(ArmEnableFiq)
+ msr daifclr, #DAIF_WR_FIQ_BIT
+ isb
+ ret
+
+
+ASM_FUNC(ArmDisableFiq)
+ msr daifset, #DAIF_WR_FIQ_BIT
+ isb
+ ret
+
+
+ASM_FUNC(ArmEnableInterrupts)
+ msr daifclr, #DAIF_WR_INT_BITS
+ isb
+ ret
+
+
+ASM_FUNC(ArmDisableInterrupts)
+ msr daifset, #DAIF_WR_INT_BITS
+ isb
+ ret
+
+
+ASM_FUNC(ArmDisableAllExceptions)
+ msr daifset, #DAIF_WR_ALL
+ isb
+ ret
+
+
+// UINT32
+// ReadCCSIDR (
+// IN UINT32 CSSELR
+// )
+ASM_FUNC(ReadCCSIDR)
+ msr csselr_el1, x0 // Write Cache Size Selection Register (CSSELR)
+ isb
+ mrs x0, ccsidr_el1 // Read current Cache Size ID Register (CCSIDR)
+ ret
+
+
+// UINT32
+// ReadCLIDR (
+// IN UINT32 CSSELR
+// )
+ASM_FUNC(ReadCLIDR)
+ mrs x0, clidr_el1 // Read Cache Level ID Register
+ ret
+
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED
|