diff --git a/ArmPkg/Library/ArmGicArchSecLib/AArch64/ArmGicArchLib.c b/ArmPkg/Library/ArmGicArchSecLib/AArch64/ArmGicArchLib.c new file mode 100644 index 0000000000..0e0fa3b9f3 --- /dev/null +++ b/ArmPkg/Library/ArmGicArchSecLib/AArch64/ArmGicArchLib.c @@ -0,0 +1,51 @@ +/** @file +* +* Copyright (c) 2014, ARM Limited. All rights reserved. +* +* This program and the accompanying materials are licensed and made available +* under the terms and conditions of the BSD License which accompanies this +* distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include +#include + +ARM_GIC_ARCH_REVISION +EFIAPI +ArmGicGetSupportedArchRevision ( + VOID + ) +{ + UINT32 IccSre; + + // Ideally we would like to use the GICC IIDR Architecture version here, but + // this does not seem to be very reliable as the implementation could easily + // get it wrong. It is more reliable to check if the GICv3 System Register + // feature is implemented on the CPU. This is also convenient as our GICv3 + // driver requires SRE. If only Memory mapped access is available we try to + // drive the GIC as a v2. + if (ArmReadIdPfr0 () & AARCH64_PFR0_GIC) { + // Make sure System Register access is enabled (SRE). This depends on the + // higher privilege level giving us permission, otherwise we will either + // cause an exception here, or the write doesn't stick in which case we need + // to fall back to the GICv2 MMIO interface. + // Note: We do not need to set ICC_SRE_EL2.Enable because the OS is started + // at the same exception level. + // It is the OS responsibility to set this bit. + IccSre = ArmGicV3GetControlSystemRegisterEnable (); + if (!(IccSre & ICC_SRE_EL2_SRE)) { + ArmGicV3SetControlSystemRegisterEnable (IccSre | ICC_SRE_EL2_SRE); + IccSre = ArmGicV3GetControlSystemRegisterEnable (); + } + if (IccSre & ICC_SRE_EL2_SRE) { + return ARM_GIC_ARCH_REVISION_3; + } + } + + return ARM_GIC_ARCH_REVISION_2; +} diff --git a/ArmPkg/Library/ArmGicArchSecLib/Arm/ArmGicArchLib.c b/ArmPkg/Library/ArmGicArchSecLib/Arm/ArmGicArchLib.c new file mode 100644 index 0000000000..f256de7046 --- /dev/null +++ b/ArmPkg/Library/ArmGicArchSecLib/Arm/ArmGicArchLib.c @@ -0,0 +1,51 @@ +/** @file +* +* Copyright (c) 2014, ARM Limited. All rights reserved. +* +* This program and the accompanying materials are licensed and made available +* under the terms and conditions of the BSD License which accompanies this +* distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include +#include + +ARM_GIC_ARCH_REVISION +EFIAPI +ArmGicGetSupportedArchRevision ( + VOID + ) +{ + UINT32 IccSre; + + // Ideally we would like to use the GICC IIDR Architecture version here, but + // this does not seem to be very reliable as the implementation could easily + // get it wrong. It is more reliable to check if the GICv3 System Register + // feature is implemented on the CPU. This is also convenient as our GICv3 + // driver requires SRE. If only Memory mapped access is available we try to + // drive the GIC as a v2. + if (ArmReadIdPfr1 () & ARM_PFR1_GIC) { + // Make sure System Register access is enabled (SRE). This depends on the + // higher privilege level giving us permission, otherwise we will either + // cause an exception here, or the write doesn't stick in which case we need + // to fall back to the GICv2 MMIO interface. + // Note: We do not need to set ICC_SRE_EL2.Enable because the OS is started + // at the same exception level. + // It is the OS responsibility to set this bit. + IccSre = ArmGicV3GetControlSystemRegisterEnable (); + if (!(IccSre & ICC_SRE_EL2_SRE)) { + ArmGicV3SetControlSystemRegisterEnable (IccSre| ICC_SRE_EL2_SRE); + IccSre = ArmGicV3GetControlSystemRegisterEnable (); + } + if (IccSre & ICC_SRE_EL2_SRE) { + return ARM_GIC_ARCH_REVISION_3; + } + } + + return ARM_GIC_ARCH_REVISION_2; +} diff --git a/ArmPkg/Library/ArmGicArchSecLib/ArmGicArchSecLib.inf b/ArmPkg/Library/ArmGicArchSecLib/ArmGicArchSecLib.inf new file mode 100644 index 0000000000..a2fb623a85 --- /dev/null +++ b/ArmPkg/Library/ArmGicArchSecLib/ArmGicArchSecLib.inf @@ -0,0 +1,33 @@ +#/* @file +# Copyright (c) 2015, Linaro Ltd. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#*/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ArmGicArchSecLib + FILE_GUID = c1dd9745-9459-4e9a-9f5b-99cbd233c27d + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = ArmGicArchLib|SEC + +[Sources.ARM] + Arm/ArmGicArchLib.c + +[Sources.AARCH64] + AArch64/ArmGicArchLib.c + +[Packages] + MdePkg/MdePkg.dec + ArmPkg/ArmPkg.dec + +[LibraryClasses] + ArmGicLib diff --git a/ArmPlatformPkg/ArmPlatformPkg-2ndstage.dsc b/ArmPlatformPkg/ArmPlatformPkg-2ndstage.dsc index e50fcb0959..dc21286e2b 100644 --- a/ArmPlatformPkg/ArmPlatformPkg-2ndstage.dsc +++ b/ArmPlatformPkg/ArmPlatformPkg-2ndstage.dsc @@ -143,6 +143,7 @@ PrePiHobListPointerLib|ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointerLib.inf PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf PlatformPeiLib|ArmPlatformPkg/PlatformPei/PlatformPeiLib.inf + ArmGicArchLib|ArmPkg/Library/ArmGicArchSecLib/ArmGicArchSecLib.inf [LibraryClasses.common.SEC, LibraryClasses.common.PEIM] MemoryInitPeiLib|ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.inf diff --git a/ArmPlatformPkg/ArmPlatformPkg.dsc b/ArmPlatformPkg/ArmPlatformPkg.dsc index 0f59fec113..5b857e57af 100644 --- a/ArmPlatformPkg/ArmPlatformPkg.dsc +++ b/ArmPlatformPkg/ArmPlatformPkg.dsc @@ -139,6 +139,8 @@ DebugAgentLib|ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.inf DefaultExceptionHandlerLib|ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLibBase.inf + ArmGicArchLib|ArmPkg/Library/ArmGicArchSecLib/ArmGicArchSecLib.inf + [LibraryClasses.common.SEC, LibraryClasses.common.PEIM] MemoryInitPeiLib|ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.inf diff --git a/ArmPlatformPkg/ArmRealViewEbPkg/ArmRealViewEb.dsc.inc b/ArmPlatformPkg/ArmRealViewEbPkg/ArmRealViewEb.dsc.inc index 4d0ecfa713..f25708f06f 100644 --- a/ArmPlatformPkg/ArmRealViewEbPkg/ArmRealViewEb.dsc.inc +++ b/ArmPlatformPkg/ArmRealViewEbPkg/ArmRealViewEb.dsc.inc @@ -137,6 +137,8 @@ PrePiHobListPointerLib|ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointerLib.inf !endif + ArmGicArchLib|ArmPkg/Library/ArmGicArchSecLib/ArmGicArchSecLib.inf + [LibraryClasses.common.SEC, LibraryClasses.common.PEIM] MemoryInitPeiLib|ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.inf diff --git a/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress.dsc.inc b/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress.dsc.inc index 3c7be4e64a..7e0d8ff4b6 100644 --- a/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress.dsc.inc +++ b/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress.dsc.inc @@ -151,6 +151,8 @@ # Trustzone Support ArmTrustedMonitorLib|ArmPlatformPkg/Library/ArmTrustedMonitorLibNull/ArmTrustedMonitorLibNull.inf + ArmGicArchLib|ArmPkg/Library/ArmGicArchSecLib/ArmGicArchSecLib.inf + [LibraryClasses.common.PEI_CORE] HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf