ArmPkg/ArmCpuLib: Replaced complex functions ArmCpuSynchronizeWait & ArmCpuSynchronizeSignal by sev & wfe

Previsouly the synchronization of MpCore was using the SGI (Software
Generated Interrupt) to synchronize MpCore during the early boot.
This commit replaced this mechanism by the more appropriate SEV/WFE
instructions (Send/Wait Event instructions).
That also eases the port to a new cpu/platform.

Signed-off-by: Olivier Martin <olivier.martin@arm.com>



git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13249 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
oliviermartin 2012-05-02 19:55:32 +00:00
parent f463bb00ad
commit b1d41be7c9
19 changed files with 61 additions and 274 deletions

View File

@ -1,6 +1,6 @@
/** @file
Copyright (c) 2011, ARM Limited. All rights reserved.
Copyright (c) 2011-2012, 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
@ -15,76 +15,15 @@
#include <Base.h>
#include <Library/ArmLib.h>
#include <Library/ArmCpuLib.h>
#include <Library/ArmGicLib.h>
#include <Library/IoLib.h>
#include <Library/PcdLib.h>
VOID
ArmCpuSynchronizeSignal (
IN ARM_CPU_SYNCHRONIZE_EVENT Event
)
{
if (Event == ARM_CPU_EVENT_BOOT_MEM_INIT) {
// Do nothing, Cortex A9 secondary cores are waiting for the SCU to be
// enabled (done by ArmCpuSetup()) as a way to know when the Init Boot
// Mem as been initialized
} else {
// Send SGI to all Secondary core to wake them up from WFI state.
ArmGicSendSgiTo (PcdGet32(PcdGicDistributorBase), ARM_GIC_ICDSGIR_FILTER_EVERYONEELSE, 0x0E);
}
}
VOID
CArmCpuSynchronizeWait (
IN ARM_CPU_SYNCHRONIZE_EVENT Event
)
{
// Waiting for the SGI from the primary core
ArmCallWFI ();
// Acknowledge the interrupt and send End of Interrupt signal.
ArmGicAcknowledgeSgiFrom (PcdGet32(PcdGicInterruptInterfaceBase), PRIMARY_CORE_ID);
}
#if 0
VOID
ArmEnableScu (
VOID
)
{
INTN ScuBase;
ScuBase = ArmGetScuBaseAddress();
// Invalidate all: write -1 to SCU Invalidate All register
MmioWrite32(ScuBase + A9_SCU_INVALL_OFFSET, 0xffffffff);
// Enable SCU
MmioWrite32(ScuBase + A9_SCU_CONTROL_OFFSET, 0x1);
}
#endif
VOID
ArmCpuSetup (
IN UINTN MpId
)
{
/*AMP mode and SMP mode
By default, the processor is in AMP mode (bit 5 reset to 0). To prevent coherent data corruption the sequence to turn on MP11 CPUs in SMP mode is:
1.Write the SCU register to change CPU mode.
2.Disable interrupts.
3.Clean and invalidate all the D-cache.
4.Write SMP/nAMP bit as 1.
5.Enable interrupts.
Source: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0360e/BIHHFGEC.html
*/
// If MPCore then Enable the SCU
if (ArmIsMpCore()) {
//ArmEnableScu ();
}
ASSERT(0); //TODO: Implement me
}
@ -93,20 +32,6 @@ ArmCpuSetupSmpNonSecure (
IN UINTN MpId
)
{
#if 0
INTN ScuBase;
ArmSetAuxCrBit (A9_FEATURE_SMP);
// Make the SCU accessible in Non Secure world
if (IS_PRIMARY_CORE(MpId)) {
ScuBase = ArmGetScuBaseAddress();
// Allow NS access to SCU register
MmioOr32 (ScuBase + A9_SCU_SACR_OFFSET, 0xf);
// Allow NS access to Private Peripherals
MmioOr32 (ScuBase + A9_SCU_SSACR_OFFSET, 0xfff);
}
#endif
ASSERT(0); //TODO: Implement me
}

View File

@ -1,5 +1,5 @@
#/* @file
# Copyright (c) 2011, ARM Limited. All rights reserved.
# Copyright (c) 2011-2012, 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
@ -25,18 +25,8 @@
[LibraryClasses]
ArmLib
ArmGicSecLib
IoLib
PcdLib
[Sources.common]
Arm11Lib.c
Arm11Helper.asm | RVCT
Arm11Helper.S | GCC
[FixedPcd]
gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
gArmTokenSpaceGuid.PcdArmPrimaryCore
gArmTokenSpaceGuid.PcdGicDistributorBase
gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase

View File

@ -1,6 +1,6 @@
/** @file
Copyright (c) 2011, ARM Limited. All rights reserved.
Copyright (c) 2011-2012, 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
@ -15,7 +15,6 @@
#include <Base.h>
#include <Library/ArmLib.h>
#include <Library/ArmCpuLib.h>
#include <Library/ArmGicLib.h>
#include <Library/ArmV7ArchTimerLib.h>
#include <Library/DebugLib.h>
#include <Library/IoLib.h>
@ -23,33 +22,6 @@
#include <Chipset/ArmV7.h>
VOID
ArmCpuSynchronizeSignal (
IN ARM_CPU_SYNCHRONIZE_EVENT Event
)
{
if (Event == ARM_CPU_EVENT_BOOT_MEM_INIT) {
// Do nothing, Cortex A15 secondary cores are waiting for the GIC Distributor
// to be enabled (done by the Sec module itself) as a way to know when the Init Boot
// Mem as been initialized
} else {
// Send SGI to all Secondary core to wake them up from WFI state.
ArmGicSendSgiTo (PcdGet32(PcdGicDistributorBase), ARM_GIC_ICDSGIR_FILTER_EVERYONEELSE, 0x0E);
}
}
VOID
CArmCpuSynchronizeWait (
IN ARM_CPU_SYNCHRONIZE_EVENT Event
)
{
// Waiting for the SGI from the primary core
ArmCallWFI ();
// Acknowledge the interrupt and send End of Interrupt signal.
ArmGicAcknowledgeSgiFrom (PcdGet32(PcdGicInterruptInterfaceBase), PRIMARY_CORE_ID);
}
VOID
ArmCpuSetup (
IN UINTN MpId

View File

@ -1,5 +1,5 @@
#/* @file
# Copyright (c) 2011, ARM Limited. All rights reserved.
# Copyright (c) 2011-2012, 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
@ -25,14 +25,11 @@
[LibraryClasses]
ArmLib
ArmGicSecLib
IoLib
PcdLib
[Sources.common]
ArmCortexA15Lib.c
ArmCortexA15Helper.asm | RVCT
ArmCortexA15Helper.S | GCC
[FeaturePcd]
@ -40,7 +37,4 @@
gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
gArmTokenSpaceGuid.PcdArmPrimaryCore
gArmTokenSpaceGuid.PcdGicDistributorBase
gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz

View File

@ -19,24 +19,6 @@
#include <Chipset/ArmV7.h>
VOID
ArmCpuSynchronizeWait (
IN ARM_CPU_SYNCHRONIZE_EVENT Event
)
{
// The CortexA8 is a Unicore CPU. We must not use Synchronization functions
ASSERT(0);
}
VOID
ArmCpuSynchronizeSignal (
IN ARM_CPU_SYNCHRONIZE_EVENT Event
)
{
// The CortexA8 is a Unicore CPU. We must not use Synchronization functions
ASSERT(0);
}
VOID
ArmCpuSetup (
IN UINTN MpId

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2011, ARM Limited. All rights reserved.
// Copyright (c) 2011-2012, 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
@ -18,24 +18,7 @@
.text
.align 3
GCC_ASM_EXPORT(ArmCpuSynchronizeWait)
GCC_ASM_EXPORT(ArmGetScuBaseAddress)
GCC_ASM_IMPORT(CArmCpuSynchronizeWait)
// VOID
// ArmCpuSynchronizeWait (
// IN ARM_CPU_SYNCHRONIZE_EVENT Event
// );
ASM_PFX(ArmCpuSynchronizeWait):
cmp r0, #ARM_CPU_EVENT_BOOT_MEM_INIT
// The SCU enabled is the event to tell us the Init Boot Memory is initialized
beq ASM_PFX(ArmWaitScuEnabled)
// Case when the stack has been set up
push {r1,lr}
LoadConstantToReg (ASM_PFX(CArmCpuSynchronizeWait), r1)
blx r1
pop {r1,lr}
bx lr
// IN None
// OUT r0 = SCU Base Address
@ -45,14 +28,3 @@ ASM_PFX(ArmGetScuBaseAddress):
// offset 0x0000 from the Private Memory Region.
mrc p15, 4, r0, c15, c0, 0
bx lr
ASM_PFX(ArmWaitScuEnabled):
// Read Configuration Base Address Register. ArmCBar cannot be called to get
// the Configuration BAR as a stack is not necessary setup. The SCU is at the
// offset 0x0000 from the Private Memory Region.
mrc p15, 4, r0, c15, c0, 0
add r0, r0, #A9_SCU_CONTROL_OFFSET
ldr r0, [r0]
cmp r0, #1
bne ASM_PFX(ArmWaitScuEnabled)
bx lr

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2011, ARM Limited. All rights reserved.
// Copyright (c) 2011-2012, 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
@ -17,28 +17,11 @@
INCLUDE AsmMacroIoLib.inc
EXPORT ArmCpuSynchronizeWait
EXPORT ArmGetScuBaseAddress
IMPORT CArmCpuSynchronizeWait
PRESERVE8
AREA ArmCortexA9Helper, CODE, READONLY
// VOID
// ArmCpuSynchronizeWait (
// IN ARM_CPU_SYNCHRONIZE_EVENT Event
// );
ArmCpuSynchronizeWait
cmp r0, #ARM_CPU_EVENT_BOOT_MEM_INIT
// The SCU enabled is the event to tell us the Init Boot Memory is initialized
beq ArmWaitScuEnabled
// Case when the stack has been set up
push {r1,lr}
LoadConstantToReg (CArmCpuSynchronizeWait, r1)
blx r1
pop {r1,lr}
bx lr
// IN None
// OUT r0 = SCU Base Address
ArmGetScuBaseAddress
@ -48,15 +31,4 @@ ArmGetScuBaseAddress
mrc p15, 4, r0, c15, c0, 0
bx lr
ArmWaitScuEnabled
// Read Configuration Base Address Register. ArmCBar cannot be called to get
// the Configuration BAR as a stack is not necessary setup. The SCU is at the
// offset 0x0000 from the Private Memory Region.
mrc p15, 4, r0, c15, c0, 0
add r0, r0, #A9_SCU_CONTROL_OFFSET
ldr r0, [r0]
cmp r0, #1
bne ArmWaitScuEnabled
bx lr
END

View File

@ -1,6 +1,6 @@
/** @file
Copyright (c) 2011, ARM Limited. All rights reserved.
Copyright (c) 2011-2012, 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
@ -15,39 +15,11 @@
#include <Base.h>
#include <Library/ArmLib.h>
#include <Library/ArmCpuLib.h>
#include <Library/ArmGicLib.h>
#include <Library/IoLib.h>
#include <Library/PcdLib.h>
#include <Chipset/ArmCortexA9.h>
VOID
ArmCpuSynchronizeSignal (
IN ARM_CPU_SYNCHRONIZE_EVENT Event
)
{
if (Event == ARM_CPU_EVENT_BOOT_MEM_INIT) {
// Do nothing, Cortex A9 secondary cores are waiting for the SCU to be
// enabled (done by ArmCpuSetup()) as a way to know when the Init Boot
// Mem as been initialized
} else {
// Send SGI to all Secondary core to wake them up from WFI state.
ArmGicSendSgiTo (PcdGet32(PcdGicDistributorBase), ARM_GIC_ICDSGIR_FILTER_EVERYONEELSE, 0x0E);
}
}
VOID
CArmCpuSynchronizeWait (
IN ARM_CPU_SYNCHRONIZE_EVENT Event
)
{
// Waiting for the SGI from the primary core
ArmCallWFI ();
// Acknowledge the interrupt and send End of Interrupt signal.
ArmGicAcknowledgeSgiFrom (PcdGet32(PcdGicInterruptInterfaceBase), PRIMARY_CORE_ID);
}
VOID
ArmEnableScu (
VOID

View File

@ -1,5 +1,5 @@
#/* @file
# Copyright (c) 2011, ARM Limited. All rights reserved.
# Copyright (c) 2011-2012, 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
@ -25,7 +25,6 @@
[LibraryClasses]
ArmLib
ArmGicSecLib
IoLib
PcdLib
@ -39,6 +38,3 @@
[FixedPcd]
gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
gArmTokenSpaceGuid.PcdArmPrimaryCore
gArmTokenSpaceGuid.PcdGicDistributorBase
gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase

View File

@ -1,6 +1,6 @@
/** @file
Copyright (c) 2011, ARM Limited. All rights reserved.
Copyright (c) 2011-2012, 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
@ -15,24 +15,6 @@
#ifndef __ARMCPU_LIB__
#define __ARMCPU_LIB__
// These are #define and not enum to be used in assembly files
#define ARM_CPU_EVENT_DEFAULT 0
#define ARM_CPU_EVENT_BOOT_MEM_INIT 1
#define ARM_CPU_EVENT_SECURE_INIT 2
typedef UINTN ARM_CPU_SYNCHRONIZE_EVENT;
VOID
ArmCpuSynchronizeWait (
IN ARM_CPU_SYNCHRONIZE_EVENT Event
);
VOID
ArmCpuSynchronizeSignal (
IN ARM_CPU_SYNCHRONIZE_EVENT Event
);
VOID
ArmCpuSetup (
IN UINTN MpId

View File

@ -438,6 +438,16 @@ ArmSetAuxCrBit (
VOID
EFIAPI
ArmCallSEV (
VOID
);
VOID
EFIAPI
ArmCallWFE (
VOID
);
ArmCallWFI (
VOID
);

View File

@ -1,7 +1,7 @@
#------------------------------------------------------------------------------
#
# Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
# Copyright (c) 2011, ARM Limited. All rights reserved.
# Copyright (c) 2011-2012, 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
@ -40,6 +40,8 @@ GCC_ASM_EXPORT(ArmUpdateTranslationTableEntry)
GCC_ASM_EXPORT(ArmWriteNsacr)
GCC_ASM_EXPORT(ArmWriteScr)
GCC_ASM_EXPORT(ArmWriteVMBar)
GCC_ASM_EXPORT(ArmCallWFE)
GCC_ASM_EXPORT(ArmCallSEV)
#------------------------------------------------------------------------------
@ -146,4 +148,12 @@ ASM_PFX(ArmWriteVMBar):
mcr p15, 0, r0, c12, c0, 1
bx lr
ASM_PFX(ArmCallWFE):
wfe
bx lr
ASM_PFX(ArmCallSEV):
sev
bx lr
ASM_FUNCTION_REMOVE_IF_UNREFERENCED

View File

@ -40,6 +40,8 @@
EXPORT ArmWriteNsacr
EXPORT ArmWriteScr
EXPORT ArmWriteVMBar
EXPORT ArmCallWFE
EXPORT ArmCallSEV
AREA ArmLibSupport, CODE, READONLY
@ -146,4 +148,12 @@ ArmWriteVMBar
mcr p15, 0, r0, c12, c0, 1
bx lr
ArmCallWFE
wfe
blx lr
ArmCallSEV
sev
blx lr
END

View File

@ -38,7 +38,6 @@
BaseLib
DebugLib
DebugAgentLib
ArmCpuLib
ArmLib
ArmGicLib
IoLib

View File

@ -1,6 +1,7 @@
#/** @file
#
# Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
# Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
#
# 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
@ -38,7 +39,6 @@
BaseLib
DebugLib
DebugAgentLib
ArmCpuLib
ArmLib
IoLib
TimerLib

View File

@ -14,7 +14,6 @@
#include <PiPei.h>
#include <Library/ArmCpuLib.h>
#include <Library/DebugAgentLib.h>
#include <Library/PrePiLib.h>
#include <Library/PrintLib.h>
@ -204,11 +203,12 @@ CEntryPoint (
if (IS_PRIMARY_CORE(MpId)) {
mGlobalVariableBase = GlobalVariableBase;
if (ArmIsMpCore()) {
ArmCpuSynchronizeSignal (ARM_CPU_EVENT_DEFAULT);
// Signal the Global Variable Region is defined (event: ARM_CPU_EVENT_DEFAULT)
ArmCallSEV ();
}
} else {
// Wait the Primay core has defined the address of the Global Variable region
ArmCpuSynchronizeWait (ARM_CPU_EVENT_DEFAULT);
// Wait the Primay core has defined the address of the Global Variable region (event: ARM_CPU_EVENT_DEFAULT)
ArmCallWFE ();
}
}

View File

@ -54,7 +54,8 @@ CEntryPoint (
// Primary CPU clears out the SCU tag RAMs, secondaries wait
if (IS_PRIMARY_CORE(MpId)) {
if (ArmIsMpCore()) {
ArmCpuSynchronizeSignal (ARM_CPU_EVENT_BOOT_MEM_INIT);
// Signal for the initial memory is configured (event: BOOT_MEM_INIT)
ArmCallSEV ();
}
// SEC phase needs to run library constructors by hand. This assumes we are linked against the SerialLib
@ -159,18 +160,18 @@ TrustedWorldInitialization (
// Setup the Trustzone Chipsets
if (IS_PRIMARY_CORE(MpId)) {
if (ArmIsMpCore()) {
// Waiting for the Primary Core to have finished to initialize the Secure World
ArmCpuSynchronizeSignal (ARM_CPU_EVENT_SECURE_INIT);
// Signal the secondary core the Security settings is done (event: EVENT_SECURE_INIT)
ArmCallSEV ();
}
} else {
// The secondary cores need to wait until the Trustzone chipsets configuration is done
// before switching to Non Secure World
// Waiting for the Primary Core to have finished to initialize the Secure World
ArmCpuSynchronizeWait (ARM_CPU_EVENT_SECURE_INIT);
// Wait for the Primary Core to finish the initialization of the Secure World (event: EVENT_SECURE_INIT)
ArmCallWFE ();
}
// Call the Platform specific fucntion to execute additional actions if required
// Call the Platform specific function to execute additional actions if required
JumpAddress = PcdGet32 (PcdFvBaseAddress);
ArmPlatformSecExtraAction (MpId, &JumpAddress);

View File

@ -26,7 +26,7 @@ GCC_ASM_IMPORT(ArmDisableCachesAndMmu)
GCC_ASM_IMPORT(ArmWriteVBar)
GCC_ASM_IMPORT(ArmReadMpidr)
GCC_ASM_IMPORT(SecVectorTable)
GCC_ASM_IMPORT(ArmCpuSynchronizeWait)
GCC_ASM_IMPORT(ArmCallWFE)
GCC_ASM_EXPORT(_ModuleEntryPoint)
StartupAddr: .word ASM_PFX(CEntryPoint)
@ -59,8 +59,8 @@ _IdentifyCpu:
beq _InitMem
_WaitInitMem:
mov r0, #ARM_CPU_EVENT_BOOT_MEM_INIT
bl ASM_PFX(ArmCpuSynchronizeWait)
// Wait for the primary core to initialize the initial memory (event: BOOT_MEM_INIT)
bl ASM_PFX(ArmCallWFE)
// Now the Init Mem is initialized, we setup the secondary core stacks
b _SetupSecondaryCoreStack

View File

@ -24,8 +24,8 @@
IMPORT ArmDisableCachesAndMmu
IMPORT ArmWriteVBar
IMPORT ArmReadMpidr
IMPORT ArmCallWFE
IMPORT SecVectorTable
IMPORT ArmCpuSynchronizeWait
EXPORT _ModuleEntryPoint
PRESERVE8
@ -61,8 +61,8 @@ _IdentifyCpu
beq _InitMem
_WaitInitMem
mov r0, #ARM_CPU_EVENT_BOOT_MEM_INIT
bl ArmCpuSynchronizeWait
// Wait for the primary core to initialize the initial memory (event: BOOT_MEM_INIT)
bl ArmCallWFE
// Now the Init Mem is initialized, we setup the secondary core stacks
b _SetupSecondaryCoreStack