diff --git a/ArmPkg/Include/AsmMacroIoLib.h b/ArmPkg/Include/AsmMacroIoLib.h index 1ea2c33ffb..9ef3430aaa 100644 --- a/ArmPkg/Include/AsmMacroIoLib.h +++ b/ArmPkg/Include/AsmMacroIoLib.h @@ -168,6 +168,17 @@ #define LoadConstantToReg(Data, Reg) \ ldr Reg, =Data +#define GetCorePositionInStack(Pos, MpId, Tmp) \ + lsr Pos, MpId, #6 ; \ + and Tmp, MpId, #3 ; \ + add Pos, Pos, Tmp + +#define SetPrimaryStack(StackTop, GlobalSize, Tmp) \ + and Tmp, GlobalSize, #7 ; \ + rsbne Tmp, Tmp, #8 ; \ + add GlobalSize, GlobalSize, Tmp ; \ + sub sp, StackTop, GlobalSize + #else // @@ -229,8 +240,10 @@ // conditional load testing eq flag #define LoadConstantToRegIfEq(Data, Reg) LoadConstantToRegIfEqMacro Data, Reg +#define GetCorePositionInStack(Pos, MpId, Tmp) GetCorePositionInStack Pos, MpId, Tmp + +#define SetPrimaryStack(StackTop,GlobalSize,Tmp) SetPrimaryStack StackTop, GlobalSize, Tmp #endif - #endif diff --git a/ArmPkg/Include/AsmMacroIoLib.inc b/ArmPkg/Include/AsmMacroIoLib.inc index 78e2ae2945..5644bf9b30 100644 --- a/ArmPkg/Include/AsmMacroIoLib.inc +++ b/ArmPkg/Include/AsmMacroIoLib.inc @@ -77,5 +77,21 @@ LoadConstantToRegMacro $Data, $Reg ldr $Reg, =($Data) MEND + + MACRO + GetCorePositionInStack $Pos, $MpId, $Tmp + lsr $Pos, $MpId, #6 + and $Tmp, $MpId, #3 + add $Pos, $Pos, $Tmp + MEND + + ; The reserved place must be 8-bytes aligned for pushing 64-bit variable on the stack + MACRO + SetPrimaryStack $StackTop, $GlobalSize, $Tmp + and $Tmp, $GlobalSize, #7 + rsbne $Tmp, $Tmp, #8 + add $GlobalSize, $GlobalSize, $Tmp + sub sp, $StackTop, $GlobalSize + MEND END diff --git a/ArmPlatformPkg/ArmPlatformPkg.dec b/ArmPlatformPkg/ArmPlatformPkg.dec index 65b4977fdb..c5e40105e6 100644 --- a/ArmPlatformPkg/ArmPlatformPkg.dec +++ b/ArmPlatformPkg/ArmPlatformPkg.dec @@ -49,19 +49,21 @@ # These PCDs should be FeaturePcds. But we used these PCDs as an '#if' in an ASM file. # Using a FeaturePcd make a '(BOOLEAN) casting for its value which is not understood by the preprocessor. gArmPlatformTokenSpaceGuid.PcdMPCoreSupport|0|UINT32|0x00000003 - gArmPlatformTokenSpaceGuid.PcdMPCoreMaxCores|1|UINT32|0x0000002D - + gArmPlatformTokenSpaceGuid.PcdClusterCount|1|UINT32|0x00000038 + # Stack for CPU Cores in Secure Mode gArmPlatformTokenSpaceGuid.PcdCPUCoresSecStackBase|0|UINT32|0x00000005 - gArmPlatformTokenSpaceGuid.PcdCPUCoreSecStackSize|0|UINT32|0x00000006 + gArmPlatformTokenSpaceGuid.PcdCPUCoreSecPrimaryStackSize|0x10000|UINT32|0x00000036 + gArmPlatformTokenSpaceGuid.PcdCPUCoreSecSecondaryStackSize|0x1000|UINT32|0x00000006 # Stack for CPU Cores in Secure Monitor Mode gArmPlatformTokenSpaceGuid.PcdCPUCoresSecMonStackBase|0|UINT32|0x00000007 - gArmPlatformTokenSpaceGuid.PcdCPUCoreSecMonStackSize|0|UINT32|0x00000008 + gArmPlatformTokenSpaceGuid.PcdCPUCoreSecMonStackSize|0x1000|UINT32|0x00000008 # Stack for CPU Cores in Non Secure Mode - gArmPlatformTokenSpaceGuid.PcdCPUCoresNonSecStackBase|0|UINT32|0x00000009 - gArmPlatformTokenSpaceGuid.PcdCPUCoresNonSecStackSize|0|UINT32|0x0000000A + gArmPlatformTokenSpaceGuid.PcdCPUCoresStackBase|0|UINT32|0x00000009 + gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize|0x10000|UINT32|0x00000037 + gArmPlatformTokenSpaceGuid.PcdCPUCoreSecondaryStackSize|0x1000|UINT32|0x0000000A # Size of the region used by UEFI in permanent memory (Reserved 128MB by default) gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize|0x08000000|UINT32|0x00000015 diff --git a/ArmPlatformPkg/ArmRealViewEbPkg/ArmRealViewEb-RTSM-A8.dsc b/ArmPlatformPkg/ArmRealViewEbPkg/ArmRealViewEb-RTSM-A8.dsc index 12f2cbb11c..808793cb2a 100644 --- a/ArmPlatformPkg/ArmRealViewEbPkg/ArmRealViewEb-RTSM-A8.dsc +++ b/ArmPlatformPkg/ArmRealViewEbPkg/ArmRealViewEb-RTSM-A8.dsc @@ -344,16 +344,11 @@ gArmTokenSpaceGuid.PcdCpuVectorBaseAddress|0x00000000 # Stack for CPU Cores in Secure Mode - gArmPlatformTokenSpaceGuid.PcdCPUCoresSecStackBase|0x4B000000 # Top of SEC Stack for Secure World - gArmPlatformTokenSpaceGuid.PcdCPUCoreSecStackSize|0x2000 # Size of SEC Stack for Secure World - + gArmPlatformTokenSpaceGuid.PcdCPUCoresSecStackBase|0x4B000000 # Stack for CPU Cores in Secure Monitor Mode - gArmPlatformTokenSpaceGuid.PcdCPUCoresSecMonStackBase|0x4A000000 # Top of SEC Stack for Monitor World - gArmPlatformTokenSpaceGuid.PcdCPUCoreSecMonStackSize|0x2000 # Size of SEC Stack for Monitor World - + gArmPlatformTokenSpaceGuid.PcdCPUCoresSecMonStackBase|0x4A000000 # Stack for CPU Cores in Non Secure Mode - gArmPlatformTokenSpaceGuid.PcdCPUCoresNonSecStackBase|0x48000000 # Top of SEC Stack for Normal World - gArmPlatformTokenSpaceGuid.PcdCPUCoresNonSecStackSize|0x20000 # Size of SEC Stack for Normal World + gArmPlatformTokenSpaceGuid.PcdCPUCoresStackBase|0x48000000 # System Memory (256MB) gArmTokenSpaceGuid.PcdSystemMemoryBase|0x70000000 diff --git a/ArmPlatformPkg/ArmRealViewEbPkg/ArmRealViewEb-RTSM-A9x2.dsc b/ArmPlatformPkg/ArmRealViewEbPkg/ArmRealViewEb-RTSM-A9x2.dsc index 1852552cd4..4c3cf6e692 100644 --- a/ArmPlatformPkg/ArmRealViewEbPkg/ArmRealViewEb-RTSM-A9x2.dsc +++ b/ArmPlatformPkg/ArmRealViewEbPkg/ArmRealViewEb-RTSM-A9x2.dsc @@ -346,19 +346,13 @@ gArmTokenSpaceGuid.PcdCpuVectorBaseAddress|0x00000000 gArmPlatformTokenSpaceGuid.PcdMPCoreSupport|1 - gArmPlatformTokenSpaceGuid.PcdMPCoreMaxCores|2 # Stacks for MPCores in Secure World - gArmPlatformTokenSpaceGuid.PcdCPUCoresSecStackBase|0x4B000000 # Top of SEC Stack for Secure World - gArmPlatformTokenSpaceGuid.PcdCPUCoreSecStackSize|0x2000 # Stack for each of the 4 CPU cores - + gArmPlatformTokenSpaceGuid.PcdCPUCoresSecStackBase|0x4B000000 # Stacks for MPCores in Monitor Mode - gArmPlatformTokenSpaceGuid.PcdCPUCoresSecMonStackBase|0x4A000000 # Top of SEC Stack for Monitor World - gArmPlatformTokenSpaceGuid.PcdCPUCoreSecMonStackSize|0x2000 # Stack for each of the 4 CPU cores - + gArmPlatformTokenSpaceGuid.PcdCPUCoresSecMonStackBase|0x4A000000 # Stacks for MPCores in Normal World - gArmPlatformTokenSpaceGuid.PcdCPUCoresNonSecStackBase|0x48000000 # Top of SEC Stack for Normal World - gArmPlatformTokenSpaceGuid.PcdCPUCoresNonSecStackSize|0x20000 # Stack for each of the 4 CPU cores + gArmPlatformTokenSpaceGuid.PcdCPUCoresStackBase|0x48000000 # System Memory (256MB) gArmTokenSpaceGuid.PcdSystemMemoryBase|0x70000000 diff --git a/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-CTA9x4.dsc b/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-CTA9x4.dsc index d4be10b022..74c28af89b 100644 --- a/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-CTA9x4.dsc +++ b/ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-CTA9x4.dsc @@ -385,20 +385,14 @@ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData|0 gArmPlatformTokenSpaceGuid.PcdMPCoreSupport|1 - gArmPlatformTokenSpaceGuid.PcdMPCoreMaxCores|4 gArmTokenSpaceGuid.PcdVFPEnabled|1 # Stacks for MPCores in Secure World - gArmPlatformTokenSpaceGuid.PcdCPUCoresSecStackBase|0x49E00000 # Top of SEC Stack for Secure World - gArmPlatformTokenSpaceGuid.PcdCPUCoreSecStackSize|0x2000 # Stack for each of the 4 CPU cores - + gArmPlatformTokenSpaceGuid.PcdCPUCoresSecStackBase|0x49E00000 # Stacks for MPCores in Monitor Mode - gArmPlatformTokenSpaceGuid.PcdCPUCoresSecMonStackBase|0x49D00000 # Top of SEC Stack for Monitor World - gArmPlatformTokenSpaceGuid.PcdCPUCoreSecMonStackSize|0x2000 # Stack for each of the 4 CPU cores - + gArmPlatformTokenSpaceGuid.PcdCPUCoresSecMonStackBase|0x49D00000 # Stacks for MPCores in Normal World - gArmPlatformTokenSpaceGuid.PcdCPUCoresNonSecStackBase|0x48000000 # Top of SEC Stack for Normal World - gArmPlatformTokenSpaceGuid.PcdCPUCoresNonSecStackSize|0x00020000 # Stack for each of the 4 CPU cores + gArmPlatformTokenSpaceGuid.PcdCPUCoresStackBase|0x48000000 # System Memory (1GB) gArmTokenSpaceGuid.PcdSystemMemoryBase|0x60000000 diff --git a/ArmPlatformPkg/Documentation/ArmPlatformPkg.txt b/ArmPlatformPkg/Documentation/ArmPlatformPkg.txt index e45a3f0666..418706fdef 100644 --- a/ArmPlatformPkg/Documentation/ArmPlatformPkg.txt +++ b/ArmPlatformPkg/Documentation/ArmPlatformPkg.txt @@ -19,18 +19,19 @@ gArmTokenSpaceGuid.PcdNormalFdBaseAddress : Base Address of your Non-Secur gArmTokenSpaceGuid.PcdNormalFdSize : Size in bytes of your Non-Secure/Normal World Firmware Device # Stacks -gArmPlatformTokenSpaceGuid.PcdCPUCoresSecStackBase : Top of Secure Stack for Secure World -gArmPlatformTokenSpaceGuid.PcdCPUCoreSecStackSize : Size of the stack for each of the 4 CPU cores -gArmPlatformTokenSpaceGuid.PcdCPUCoresSecMonStackBase : Top of Stack for Monitor World -gArmPlatformTokenSpaceGuid.PcdCPUCoreSecMonStackSize : Size of the stack for each of the 4 CPU cores -gArmPlatformTokenSpaceGuid.PcdCPUCoresNonSecStackBase : Top of SEC Stack for Normal World -gArmPlatformTokenSpaceGuid.PcdCPUCoresNonSecStackSize : Size of the stack for each of the 4 CPU Cores +gArmPlatformTokenSpaceGuid.PcdCPUCoresSecStackBase : Base of Secure Stack for Secure World +gArmPlatformTokenSpaceGuid.PcdCPUCoreSecPrimaryStackSize : Size of the stack for the Primary Core in Secure World +gArmPlatformTokenSpaceGuid.PcdCPUCoreSecSecondaryStackSize : Size of the stack for the Secondary Cores in Secure World +gArmPlatformTokenSpaceGuid.PcdCPUCoresSecMonStackBase : Base of Stack for Monitor World +gArmPlatformTokenSpaceGuid.PcdCPUCoreSecMonStackSize : Size of the stack for each cores +gArmPlatformTokenSpaceGuid.PcdCPUCoresStackBase : Base of SEC Stack for Normal World +gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize : Size of the stack for the Primary Core +gArmPlatformTokenSpaceGuid.PcdCPUCoreSecondaryStackSize : Size of the stack for the Secondary Core # CPU / Architectural controllers gArmTokenSpaceGuid.PcdGicDistributorBase : Base address of the Distributor of your General Interrupt Controller gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase : Base address of the Interface of your General Interrupt Controller gArmPlatformTokenSpaceGuid.PcdMPCoreSupport : Set to 1 when MP Core platforms -gArmPlatformTokenSpaceGuid.PcdMPCoreMaxCores : Maximum number of CPU cores on the platform (used for instance to know how many stacks we need to configure) # Memory Regions gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize : Size of the region reserve for PI & UEFI diff --git a/ArmPlatformPkg/PrePeiCore/MainMPCore.c b/ArmPlatformPkg/PrePeiCore/MainMPCore.c index 036b192064..732e751c95 100644 --- a/ArmPlatformPkg/PrePeiCore/MainMPCore.c +++ b/ArmPlatformPkg/PrePeiCore/MainMPCore.c @@ -82,8 +82,8 @@ PrimaryMain ( SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF); SecCoreData.BootFirmwareVolumeBase = (VOID *)(UINTN)PcdGet32 (PcdNormalFvBaseAddress); SecCoreData.BootFirmwareVolumeSize = PcdGet32 (PcdNormalFvSize); - SecCoreData.TemporaryRamBase = (VOID *)(UINTN)PcdGet32 (PcdCPUCoresNonSecStackBase); // We consider we run on the primary core (and so we use the first stack) - SecCoreData.TemporaryRamSize = (UINTN)(UINTN)PcdGet32 (PcdCPUCoresNonSecStackSize); + SecCoreData.TemporaryRamBase = (VOID *)(UINTN)PcdGet32 (PcdCPUCorePrimaryStackSize); // We consider we run on the primary core (and so we use the first stack) + SecCoreData.TemporaryRamSize = (UINTN)(UINTN)PcdGet32 (PcdCPUCorePrimaryStackSize); SecCoreData.PeiTemporaryRamBase = (VOID *)((UINTN)(SecCoreData.TemporaryRamBase) + (SecCoreData.TemporaryRamSize / 2)); SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize / 2; SecCoreData.StackBase = SecCoreData.TemporaryRamBase; diff --git a/ArmPlatformPkg/PrePeiCore/MainUniCore.c b/ArmPlatformPkg/PrePeiCore/MainUniCore.c index 179e1ea344..64877d1cc1 100644 --- a/ArmPlatformPkg/PrePeiCore/MainUniCore.c +++ b/ArmPlatformPkg/PrePeiCore/MainUniCore.c @@ -44,8 +44,8 @@ PrimaryMain ( SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF); SecCoreData.BootFirmwareVolumeBase = (VOID *)(UINTN)PcdGet32 (PcdNormalFvBaseAddress); SecCoreData.BootFirmwareVolumeSize = PcdGet32 (PcdNormalFvSize); - SecCoreData.TemporaryRamBase = (VOID *)(UINTN)PcdGet32 (PcdCPUCoresNonSecStackBase); // We consider we run on the primary core (and so we use the first stack) - SecCoreData.TemporaryRamSize = (UINTN)(UINTN)PcdGet32 (PcdCPUCoresNonSecStackSize); + SecCoreData.TemporaryRamBase = (VOID *)(UINTN)PcdGet32 (PcdCPUCorePrimaryStackSize); // We consider we run on the primary core (and so we use the first stack) + SecCoreData.TemporaryRamSize = (UINTN)(UINTN)PcdGet32 (PcdCPUCorePrimaryStackSize); SecCoreData.PeiTemporaryRamBase = (VOID *)((UINTN)(SecCoreData.TemporaryRamBase) + (SecCoreData.TemporaryRamSize / 2)); SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize / 2; SecCoreData.StackBase = SecCoreData.TemporaryRamBase; diff --git a/ArmPlatformPkg/PrePeiCore/PrePeiCoreEntryPoint.S b/ArmPlatformPkg/PrePeiCore/PrePeiCoreEntryPoint.S index 01723a2eac..f9b85a604e 100644 --- a/ArmPlatformPkg/PrePeiCore/PrePeiCoreEntryPoint.S +++ b/ArmPlatformPkg/PrePeiCore/PrePeiCoreEntryPoint.S @@ -26,43 +26,68 @@ GCC_ASM_EXPORT(_ModuleEntryPoint) StartupAddr: .word CEntryPoint ASM_PFX(_ModuleEntryPoint): - # Identify CPU ID + // Identify CPU ID bl ASM_PFX(ArmReadMpidr) // Get ID of this CPU in Multicore system LoadConstantToReg (FixedPcdGet32(PcdArmPrimaryCoreMask), r1) and r0, r0, r1 -_SetupStack: - # Setup Stack for the 4 CPU cores - LoadConstantToReg (FixedPcdGet32(PcdCPUCoresNonSecStackBase), r1) - LoadConstantToReg (FixedPcdGet32(PcdCPUCoresNonSecStackSize), r2) - - mov r3,r0 @ r3 = core_id - mul r3,r3,r2 @ r3 = core_id * stack_size = offset from the stack base - add r3,r3,r1 @ r3 = stack_base + offset - add r3,r3,r2,LSR #1 @ r3 = stack_offset + (stack_size/2) <-- the top half is for the heap - mov sp, r3 + // Calculate the top of the primary stack + LoadConstantToReg (FixedPcdGet32(PcdCPUCoresStackBase), r1) + LoadConstantToReg (FixedPcdGet32(PcdCPUCorePrimaryStackSize), r2) + add r2, r2, r1 - # Only allocate memory in top of the primary core stack - cmp r0, #0 - bne _PrepareArguments + // Is it the Primary Core ? + LoadConstantToReg (FixedPcdGet32(PcdArmPrimaryCore), r1) + cmp r0, r1 + beq _SetupPrimaryCoreStack -_AllocateGlobalPeiVariables: - # Reserve top of the stack for Global PEI Variables (eg: PeiServicesTablePointer) - LoadConstantToReg (FixedPcdGet32(PcdPeiGlobalVariableSize), r1) - sub sp, sp, r1 +_SetupSecondaryCoreStack: + // r2 = Top of the primary stack = Base of the Secondary Stacks + + // Get the position of the cores (ClusterId * 4) + CoreId + GetCorePositionInStack(r3, r0, r1) + // The stack starts at the top of the stack region. Add '1' to the Core Position to get the top of the stack + add r3, r3, #1 + + LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecondaryStackSize), r1) + // StackOffset = CorePos * StackSize + mul r3, r3, r1 + // SP = StackBase + StackOffset + add sp, r2, r3 + + b _PrepareArguments + +_SetupPrimaryCoreStack: + // r2 = Top of the primary stack + LoadConstantToReg (FixedPcdGet32(PcdPeiGlobalVariableSize), r3) + + // The reserved space for global variable must be 8-bytes aligned for pushing + // 64-bit variable on the stack + SetPrimaryStack (r2, r3, r1) + + // Set all the PEI global variables to 0 + mov r3, sp + mov r1, #0x0 +_InitGlobals: + str r1, [r3], #4 + cmp r3, r2 + blt _InitGlobals _PrepareArguments: - # The PEI Core Entry Point has been computed by GenFV and stored in the second entry of the Reset Vector + // The PEI Core Entry Point has been computed by GenFV and stored in the second entry of the Reset Vector LoadConstantToReg (FixedPcdGet32(PcdNormalFvBaseAddress), r2) add r2, r2, #4 ldr r1, [r2] - # move sec startup address into a data register - # ensure we're jumping to FV version of the code (not boot remapped alias) + // move sec startup address into a data register + // ensure we're jumping to FV version of the code (not boot remapped alias) ldr r2, StartupAddr - # jump to PrePeiCore C code - # r0 = core_id - # r1 = pei_core_address + // jump to PrePeiCore C code + // r0 = mp_id + // r1 = pei_core_address blx r2 + +_NeverReturn: + b _NeverReturn diff --git a/ArmPlatformPkg/PrePeiCore/PrePeiCoreEntryPoint.asm b/ArmPlatformPkg/PrePeiCore/PrePeiCoreEntryPoint.asm index e4eb612610..1964f18ebf 100644 --- a/ArmPlatformPkg/PrePeiCore/PrePeiCoreEntryPoint.asm +++ b/ArmPlatformPkg/PrePeiCore/PrePeiCoreEntryPoint.asm @@ -34,25 +34,47 @@ _ModuleEntryPoint LoadConstantToReg (FixedPcdGet32(PcdArmPrimaryCoreMask), r1) and r0, r0, r1 -_SetupStack - // Setup Stack for the 4 CPU cores - LoadConstantToReg (FixedPcdGet32(PcdCPUCoresNonSecStackBase), r1) - LoadConstantToReg (FixedPcdGet32(PcdCPUCoresNonSecStackSize), r2) - - mov r3, r0 // r3 = core_id - mul r3, r3, r2 // r3 = core_id * stack_size = offset from the stack base - add r3, r3, r1 // r3 = stack_base + offset - add r3, r3, r2, LSR #1 // r3 = stack_offset + (stack_size/2) <-- the top half is for the heap - mov sp, r3 + // Calculate the top of the primary stack + LoadConstantToReg (FixedPcdGet32(PcdCPUCoresStackBase), r1) + LoadConstantToReg (FixedPcdGet32(PcdCPUCorePrimaryStackSize), r2) + add r2, r2, r1 - // Only allocate memory in top of the primary core stack - cmp r0, #0 - bne _PrepareArguments + // Is it the Primary Core ? + LoadConstantToReg (FixedPcdGet32(PcdArmPrimaryCore), r1) + cmp r0, r1 + beq _SetupPrimaryCoreStack -_AllocateGlobalPeiVariables - // Reserve top of the stack for Global PEI Variables (eg: PeiServicesTablePointer) - LoadConstantToReg (FixedPcdGet32(PcdPeiGlobalVariableSize), r1) - sub sp, sp, r1 +_SetupSecondaryCoreStack + // r2 = Top of the primary stack = Base of the Secondary Stacks + + // Get the position of the cores (ClusterId * 4) + CoreId + GetCorePositionInStack(r3, r0, r1) + // The stack starts at the top of the stack region. Add '1' to the Core Position to get the top of the stack + add r3, r3, #1 + + LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecondaryStackSize), r1) + // StackOffset = CorePos * StackSize + mul r3, r3, r1 + // SP = StackBase + StackOffset + add sp, r2, r3 + + b _PrepareArguments + +_SetupPrimaryCoreStack + // r2 = Top of the primary stack + LoadConstantToReg (FixedPcdGet32(PcdPeiGlobalVariableSize), r3) + + // The reserved space for global variable must be 8-bytes aligned for pushing + // 64-bit variable on the stack + SetPrimaryStack (r2, r3, r1) + + // Set all the PEI global variables to 0 + mov r3, sp + mov r1, #0x0 +_InitGlobals + str r1, [r3], #4 + cmp r3, r2 + blt _InitGlobals _PrepareArguments // The PEI Core Entry Point has been computed by GenFV and stored in the second entry of the Reset Vector @@ -69,4 +91,7 @@ _PrepareArguments // r1 = pei_core_address blx r2 +_NeverReturn + b _NeverReturn + END diff --git a/ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf b/ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf index 25dae0fb9e..145893505d 100644 --- a/ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf +++ b/ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf @@ -61,8 +61,9 @@ gArmTokenSpaceGuid.PcdArmPrimaryCoreMask gArmTokenSpaceGuid.PcdArmPrimaryCore - gArmPlatformTokenSpaceGuid.PcdCPUCoresNonSecStackBase - gArmPlatformTokenSpaceGuid.PcdCPUCoresNonSecStackSize + gArmPlatformTokenSpaceGuid.PcdCPUCoresStackBase + gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize + gArmPlatformTokenSpaceGuid.PcdCPUCoreSecondaryStackSize gArmPlatformTokenSpaceGuid.PcdPeiGlobalVariableSize diff --git a/ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf b/ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf index be846c581c..028330d03b 100644 --- a/ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf +++ b/ArmPlatformPkg/PrePeiCore/PrePeiCoreUniCore.inf @@ -56,8 +56,12 @@ gArmTokenSpaceGuid.PcdNormalFvBaseAddress gArmTokenSpaceGuid.PcdNormalFvSize - gArmPlatformTokenSpaceGuid.PcdCPUCoresNonSecStackBase - gArmPlatformTokenSpaceGuid.PcdCPUCoresNonSecStackSize + gArmTokenSpaceGuid.PcdArmPrimaryCoreMask + gArmTokenSpaceGuid.PcdArmPrimaryCore + + gArmPlatformTokenSpaceGuid.PcdCPUCoresStackBase + gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize + gArmPlatformTokenSpaceGuid.PcdCPUCoreSecondaryStackSize gArmPlatformTokenSpaceGuid.PcdPeiGlobalVariableSize diff --git a/ArmPlatformPkg/PrePi/ModuleEntryPoint.S b/ArmPlatformPkg/PrePi/ModuleEntryPoint.S index 4d64aa7e86..b5f2ee2e57 100755 --- a/ArmPlatformPkg/PrePi/ModuleEntryPoint.S +++ b/ArmPlatformPkg/PrePi/ModuleEntryPoint.S @@ -19,9 +19,9 @@ .text .align 3 -# Global symbols referenced by this module GCC_ASM_IMPORT(CEntryPoint) GCC_ASM_IMPORT(ArmReadMpidr) +GCC_ASM_IMPORT(ArmIsMPCore) GCC_ASM_EXPORT(_ModuleEntryPoint) StartupAddr: .word CEntryPoint @@ -31,14 +31,14 @@ ASM_PFX(_ModuleEntryPoint): // Get ID of this CPU in Multicore system bl ASM_PFX(ArmReadMpidr) LoadConstantToReg (FixedPcdGet32(PcdArmPrimaryCoreMask), r1) - and r0, r0, r1 + and r5, r0, r1 _SetSVCMode: // Enter SVC mode mov r1, #0x13|0x80|0x40 msr CPSR_c, r1 -// Check if we can install the size at the top of the System Memory or if we need +// Check if we can install the stack at the top of the System Memory or if we need // to install the stacks at the bottom of the Firmware Device (case the FD is located // at the top of the DRAM) _SetupStackPosition: @@ -60,35 +60,77 @@ _SetupStackPosition: // // Calculate how much space there is between the top of the Firmware and the Top of the System Memory - subs r5, r1, r3 // r5 = SystemMemoryTop - FdTop - bmi _SetupStack // Jump if negative (FdTop > SystemMemoryTop) - cmp r5, r4 + subs r0, r1, r3 // r0 = SystemMemoryTop - FdTop + bmi _SetupStack // Jump if negative (FdTop > SystemMemoryTop). Case when the PrePi is in XIP memory outside of the DRAM + cmp r0, r4 bge _SetupStack // Case the top of stacks is the FdBaseAddress mov r1, r2 _SetupStack: - // Compute Base of Normal stacks for CPU Cores - LoadConstantToReg (FixedPcdGet32(PcdCPUCoresNonSecStackSize), r5) - mul r3, r0, r5 // r3 = core_id * stack_size = offset from the stack base - sub sp, r1, r3 // r3 = (SystemMemoryTop|FdBaseAddress) - StackOffset = TopOfStack + // r1 contains the top of the stack (and the UEFI Memory) // Calculate the Base of the UEFI Memory - sub r1, r1, r4 + sub r6, r1, r4 - // Only allocate memory for global variables at top of the primary core stack +_GetStackBase: + // Compute Base of Normal stacks for CPU Cores + // Is it MpCore system + bl ArmIsMPCore cmp r0, #0 + // Case it is not an MP Core system. Just setup the primary core + beq _SetupUnicoreStack + +_GetStackBaseMpCore: + // Stack for the primary core = PrimaryCoreStack + LoadConstantToReg (FixedPcdGet32(PcdCPUCorePrimaryStackSize), r2) + sub r7, r1, r2 + // Stack for the secondary core = Number of Cluster * (4 Core per cluster) * SecondaryStackSize + LoadConstantToReg (FixedPcdGet32(PcdClusterCount), r2) + lsl r2, r2, #2 + LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecondaryStackSize), r3) + mul r2, r2, r3 + sub r7, r7, r2 + + // The top of the Mpcore Stacks is in r1 + // The base of the MpCore Stacks is in r7 + + // Is it the Primary Core ? + LoadConstantToReg (FixedPcdGet32(PcdArmPrimaryCore), r4) + cmp r0, r4 + beq _SetupPrimaryCoreStack + +_SetupSecondaryCoreStack: + // Base of the stack for the secondary cores is in r7 + + // Get the position of the cores (ClusterId * 4) + CoreId + GetCorePositionInStack(r0, r5, r4) + // The stack starts at the top of the stack region. Add '1' to the Core Position to get the top of the stack + add r0, r0, #1 + // Get the offset for the Secondary Stack + mul r0, r0, r3 + add sp, r7, r0 + bne _PrepareArguments -_AllocateGlobalPrePiVariables: - // Reserve top of the stack for Global PEI Variables (eg: PeiServicesTablePointer) - LoadConstantToReg (FixedPcdGet32(PcdPeiGlobalVariableSize), r4) - // The reserved place must be 8-bytes aligned for pushing 64-bit variable on the stack - and r5, r4, #7 - rsb r5, r5, #8 - add r4, r4, r5 - sub sp, sp, r4 +_SetupPrimaryCoreStack: + // The top of the Mpcore Stacks is in r1 + LoadConstantToReg (FixedPcdGet32(PcdPeiGlobalVariableSize), r2) + + // The reserved space for global variable must be 8-bytes aligned for pushing + // 64-bit variable on the stack + SetPrimaryStack (r1, r2, r3) + +_SetGlobals: + // Set all the PrePi global variables to 0 + mov r3, sp + mov r2, #0x0 +_InitGlobals: + str r2, [r3], #4 + cmp r3, r1 + blt _InitGlobals + _PrepareArguments: // Move sec startup address into a data register @@ -100,3 +142,20 @@ _PrepareArguments: // r1 = UefiMemoryBase blx r2 +_NeverReturn: + b _NeverReturn + +_SetupUnicoreStack: + // The top of the Unicore Stack is in r1 + LoadConstantToReg (FixedPcdGet32(PcdPeiGlobalVariableSize), r2) + LoadConstantToReg (FixedPcdGet32(PcdCPUCorePrimaryStackSize), r3) + + // Calculate the bottom of the primary stack (StackBase) + sub r7, r1, r3 + + // The reserved space for global variable must be 8-bytes aligned for pushing + // 64-bit variable on the stack + SetPrimaryStack (r1, r2, r3) + + b _SetGlobals + diff --git a/ArmPlatformPkg/PrePi/ModuleEntryPoint.asm b/ArmPlatformPkg/PrePi/ModuleEntryPoint.asm index 881871d34e..965bb00318 100644 --- a/ArmPlatformPkg/PrePi/ModuleEntryPoint.asm +++ b/ArmPlatformPkg/PrePi/ModuleEntryPoint.asm @@ -20,6 +20,7 @@ IMPORT CEntryPoint IMPORT ArmReadMpidr + IMPORT ArmIsMPCore EXPORT _ModuleEntryPoint PRESERVE8 @@ -38,7 +39,7 @@ _SetSVCMode mov r1, #0x13|0x80|0x40 msr CPSR_c, r1 -// Check if we can install the size at the top of the System Memory or if we need +// Check if we can install the stack at the top of the System Memory or if we need // to install the stacks at the bottom of the Firmware Device (case the FD is located // at the top of the DRAM) _SetupStackPosition @@ -60,35 +61,77 @@ _SetupStackPosition // // Calculate how much space there is between the top of the Firmware and the Top of the System Memory - subs r5, r1, r3 // r5 = SystemMemoryTop - FdTop - bmi _SetupStack // Jump if negative (FdTop > SystemMemoryTop) - cmp r5, r4 + subs r0, r1, r3 // r0 = SystemMemoryTop - FdTop + bmi _SetupStack // Jump if negative (FdTop > SystemMemoryTop). Case when the PrePi is in XIP memory outside of the DRAM + cmp r0, r4 bge _SetupStack // Case the top of stacks is the FdBaseAddress mov r1, r2 _SetupStack - // Compute Base of Normal stacks for CPU Cores - LoadConstantToReg (FixedPcdGet32(PcdCPUCoresNonSecStackSize), r5) - mul r3, r0, r5 // r3 = core_id * stack_size = offset from the stack base - sub sp, r1, r3 // r3 = (SystemMemoryTop|FdBaseAddress) - StackOffset = TopOfStack + // r1 contains the top of the stack (and the UEFI Memory) // Calculate the Base of the UEFI Memory - sub r1, r1, r4 + sub r6, r1, r4 - // Only allocate memory for global variables at top of the primary core stack +_GetStackBase + // Compute Base of Normal stacks for CPU Cores + // Is it MpCore system + bl ArmIsMPCore cmp r0, #0 + // Case it is not an MP Core system. Just setup the primary core + beq _SetupUnicoreStack + +_GetStackBaseMpCore + // Stack for the primary core = PrimaryCoreStack + LoadConstantToReg (FixedPcdGet32(PcdCPUCorePrimaryStackSize), r2) + sub r7, r1, r2 + // Stack for the secondary core = Number of Cluster * (4 Core per cluster) * SecondaryStackSize + LoadConstantToReg (FixedPcdGet32(PcdClusterCount), r2) + lsl r2, r2, #2 + LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecondaryStackSize), r3) + mul r2, r2, r3 + sub r7, r7, r2 + + // The top of the Mpcore Stacks is in r1 + // The base of the MpCore Stacks is in r7 + + // Is it the Primary Core ? + LoadConstantToReg (FixedPcdGet32(PcdArmPrimaryCore), r4) + cmp r0, r4 + beq _SetupPrimaryCoreStack + +_SetupSecondaryCoreStack + // Base of the stack for the secondary cores is in r7 + + // Get the position of the cores (ClusterId * 4) + CoreId + GetCorePositionInStack(r0, r5, r4) + // The stack starts at the top of the stack region. Add '1' to the Core Position to get the top of the stack + add r0, r0, #1 + // Get the offset for the Secondary Stack + mul r0, r0, r3 + add sp, r7, r0 + bne _PrepareArguments -_AllocateGlobalPrePiVariables - // Reserve top of the stack for Global PEI Variables (eg: PeiServicesTablePointer) - LoadConstantToReg (FixedPcdGet32(PcdPeiGlobalVariableSize), r4) - // The reserved place must be 8-bytes aligned for pushing 64-bit variable on the stack - and r5, r4, #7 - rsb r5, r5, #8 - add r4, r4, r5 - sub sp, sp, r4 +_SetupPrimaryCoreStack + // The top of the Mpcore Stacks is in r1 + LoadConstantToReg (FixedPcdGet32(PcdPeiGlobalVariableSize), r2) + + // The reserved space for global variable must be 8-bytes aligned for pushing + // 64-bit variable on the stack + SetPrimaryStack (r1, r2, r3) + +_SetGlobals + // Set all the PrePi global variables to 0 + mov r3, sp + mov r2, #0x0 +_InitGlobals + str r2, [r3], #4 + cmp r3, r1 + blt _InitGlobals + _PrepareArguments // Move sec startup address into a data register @@ -100,4 +143,21 @@ _PrepareArguments // r1 = UefiMemoryBase blx r2 +_NeverReturn + b _NeverReturn + +_SetupUnicoreStack + // The top of the Unicore Stack is in r1 + LoadConstantToReg (FixedPcdGet32(PcdPeiGlobalVariableSize), r2) + LoadConstantToReg (FixedPcdGet32(PcdCPUCorePrimaryStackSize), r3) + + // Calculate the bottom of the primary stack (StackBase) + sub r7, r1, r3 + + // The reserved space for global variable must be 8-bytes aligned for pushing + // 64-bit variable on the stack + SetPrimaryStack (r1, r2, r3) + + b _SetGlobals + END diff --git a/ArmPlatformPkg/PrePi/PeiMPCore.inf b/ArmPlatformPkg/PrePi/PeiMPCore.inf index c8af14d19a..f141dc03be 100755 --- a/ArmPlatformPkg/PrePi/PeiMPCore.inf +++ b/ArmPlatformPkg/PrePi/PeiMPCore.inf @@ -70,8 +70,9 @@ gArmTokenSpaceGuid.PcdNormalFvBaseAddress gArmTokenSpaceGuid.PcdNormalFvSize - gArmPlatformTokenSpaceGuid.PcdCPUCoresNonSecStackBase - gArmPlatformTokenSpaceGuid.PcdCPUCoresNonSecStackSize + gArmPlatformTokenSpaceGuid.PcdCPUCoresStackBase + gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize + gArmPlatformTokenSpaceGuid.PcdCPUCoreSecondaryStackSize gArmPlatformTokenSpaceGuid.PcdPeiGlobalVariableSize gArmPlatformTokenSpaceGuid.PcdHobListPtrGlobalOffset @@ -83,7 +84,10 @@ gArmTokenSpaceGuid.PcdSystemMemorySize gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize - gArmPlatformTokenSpaceGuid.PcdMPCoreMaxCores + gArmPlatformTokenSpaceGuid.PcdClusterCount + gArmTokenSpaceGuid.PcdArmPrimaryCoreMask + gArmTokenSpaceGuid.PcdArmPrimaryCore + gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize diff --git a/ArmPlatformPkg/PrePi/PeiUniCore.inf b/ArmPlatformPkg/PrePi/PeiUniCore.inf index 5882afc13a..ccf421ca69 100755 --- a/ArmPlatformPkg/PrePi/PeiUniCore.inf +++ b/ArmPlatformPkg/PrePi/PeiUniCore.inf @@ -68,8 +68,8 @@ gArmTokenSpaceGuid.PcdNormalFvBaseAddress gArmTokenSpaceGuid.PcdNormalFvSize - gArmPlatformTokenSpaceGuid.PcdCPUCoresNonSecStackBase - gArmPlatformTokenSpaceGuid.PcdCPUCoresNonSecStackSize + gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize + gArmPlatformTokenSpaceGuid.PcdCPUCoreSecondaryStackSize gArmPlatformTokenSpaceGuid.PcdPeiGlobalVariableSize gArmPlatformTokenSpaceGuid.PcdHobListPtrGlobalOffset diff --git a/ArmPlatformPkg/PrePi/PrePi.c b/ArmPlatformPkg/PrePi/PrePi.c index a0198d89b8..64c371c803 100755 --- a/ArmPlatformPkg/PrePi/PrePi.c +++ b/ArmPlatformPkg/PrePi/PrePi.c @@ -79,7 +79,6 @@ PrePiMain ( SaveAndSetDebugTimerInterrupt (TRUE); UefiMemoryTop = UefiMemoryBase + FixedPcdGet32 (PcdSystemMemoryUefiRegionSize); - StacksSize = PcdGet32 (PcdCPUCoresNonSecStackSize) * PcdGet32 (PcdMPCoreMaxCores); StacksBase = UefiMemoryTop - StacksSize; // Check the PcdCPUCoresNonSecStackBase match with the calculated StackBase @@ -99,6 +98,7 @@ PrePiMain ( ASSERT_EFI_ERROR (Status); // Create the Stacks HOB (reserve the memory for all stacks) + StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize) + (FixedPcdGet32(PcdClusterCount) * 4 * FixedPcdGet32(PcdCPUCoreSecondaryStackSize)); BuildStackHob (StacksBase, StacksSize); // Set the Boot Mode diff --git a/ArmPlatformPkg/Sec/Sec.inf b/ArmPlatformPkg/Sec/Sec.inf index 7b116c7fd9..d2c5083c21 100644 --- a/ArmPlatformPkg/Sec/Sec.inf +++ b/ArmPlatformPkg/Sec/Sec.inf @@ -59,7 +59,8 @@ gArmTokenSpaceGuid.PcdNormalFvBaseAddress gArmPlatformTokenSpaceGuid.PcdCPUCoresSecStackBase - gArmPlatformTokenSpaceGuid.PcdCPUCoreSecStackSize + gArmPlatformTokenSpaceGuid.PcdCPUCoreSecPrimaryStackSize + gArmPlatformTokenSpaceGuid.PcdCPUCoreSecSecondaryStackSize gArmPlatformTokenSpaceGuid.PcdCPUCoresSecMonStackBase gArmPlatformTokenSpaceGuid.PcdCPUCoreSecMonStackSize diff --git a/ArmPlatformPkg/Sec/SecEntryPoint.S b/ArmPlatformPkg/Sec/SecEntryPoint.S index 5d83bf1ee7..7f13057f6b 100644 --- a/ArmPlatformPkg/Sec/SecEntryPoint.S +++ b/ArmPlatformPkg/Sec/SecEntryPoint.S @@ -1,34 +1,27 @@ -#------------------------------------------------------------------------------ -# -# ARM VE Entry point. Reset vector in FV header will brach to -# _ModuleEntryPoint. -# -# Copyright (c) 2011, 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. -# -#------------------------------------------------------------------------------ +// +// Copyright (c) 2011, 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 #include #include #include -#include -#Start of Code section .text .align 3 -#make _ModuleEntryPoint as global GCC_ASM_EXPORT(_ModuleEntryPoint) -#global functions referenced by this module GCC_ASM_IMPORT(CEntryPoint) GCC_ASM_IMPORT(ArmPlatformSecBootAction) GCC_ASM_IMPORT(ArmPlatformInitializeBootMemory) @@ -42,75 +35,99 @@ GCC_ASM_IMPORT(SecVectorTable) GCC_ASM_IMPORT(ArmIsScuEnable) #endif -StartupAddr: .word ASM_PFX(CEntryPoint) -SecVectorTableAddr: .word ASM_PFX(SecVectorTable) +StartupAddr: .word ASM_PFX(CEntryPoint) +SecVectorTableAddr: .word ASM_PFX(SecVectorTable) ASM_PFX(_ModuleEntryPoint): - # First ensure all interrupts are disabled - bl ASM_PFX(ArmDisableInterrupts) + // First ensure all interrupts are disabled + bl ASM_PFX(ArmDisableInterrupts) - # Ensure that the MMU and caches are off - bl ASM_PFX(ArmDisableCachesAndMmu) + // Ensure that the MMU and caches are off + bl ASM_PFX(ArmDisableCachesAndMmu) - # Jump to Platform Specific Boot Action function + // Jump to Platform Specific Boot Action function blx ASM_PFX(ArmPlatformSecBootAction) - # Set VBAR to the start of the exception vectors in Secure Mode + // Set VBAR to the start of the exception vectors in Secure Mode ldr r0, =SecVectorTable bl ASM_PFX(ArmWriteVBar) -_IdentifyCpu: - # Identify CPU ID +_IdentifyCpu: + // Identify CPU ID bl ASM_PFX(ArmReadMpidr) // Get ID of this CPU in Multicore system LoadConstantToReg (FixedPcdGet32(PcdArmPrimaryCoreMask), r1) and r5, r0, r1 - #get ID of this CPU in Multicore system + // Is it the Primary Core ? LoadConstantToReg (FixedPcdGet32(PcdArmPrimaryCore), r1) cmp r5, r1 - # Only the primary core initialize the memory (SMC) + // Only the primary core initialize the memory (SMC) beq _InitMem #if (FixedPcdGet32(PcdMPCoreSupport)) - # ... The secondary cores wait for SCU to be enabled + // ... The secondary cores wait for SCU to be enabled _WaitForEnabledScu: bl ASM_PFX(ArmIsScuEnable) tst r1, #1 beq _WaitForEnabledScu - b _SetupStack + b _SetupSecondaryCoreStack #endif _InitMem: // Initialize Init Boot Memory bl ASM_PFX(ArmPlatformInitializeBootMemory) - - # Only Primary CPU could run this line (the secondary cores have jumped from _IdentifyCpu to _SetupStack) - mov r5, #0 - -_SetupStack: - # Setup Stack for the 4 CPU cores - #Read Stack Base address from PCD - LoadConstantToReg (FixedPcdGet32(PcdCPUCoresSecStackBase), r1) - - #read Stack size from PCD - LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecStackSize), r2) - - #calcuate Stack Pointer reg value using Stack size and CPU ID. - mov r3,r5 @ r3 = core_id - mul r3,r3,r2 @ r3 = core_id * stack_size = offset from the stack base - add r3,r3,r1 @ r3 ldr= stack_base + offset - mov sp, r3 - # move sec startup address into a data register - # ensure we're jumping to FV version of the code (not boot remapped alias) + // Only Primary CPU could run this line (the secondary cores have jumped from _IdentifyCpu to _SetupStack) + LoadConstantToReg (FixedPcdGet32(PcdArmPrimaryCore), r5) + +_SetupPrimaryCoreStack: + LoadConstantToReg (FixedPcdGet32(PcdCPUCoresSecStackBase), r2) + LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecPrimaryStackSize), r3) + // Calculate the Top of the Stack + add r2, r2, r3 + LoadConstantToReg (FixedPcdGet32(PcdSecGlobalVariableSize), r3) + + // The reserved space for global variable must be 8-bytes aligned for pushing + // 64-bit variable on the stack + SetPrimaryStack (r2, r3, r1) + + // Set all the SEC global variables to 0 + mov r3, sp + mov r1, #0x0 +_InitGlobals: + str r1, [r3], #4 + cmp r3, r2 + blt _InitGlobals + + b _PrepareArguments + +_SetupSecondaryCoreStack: + // Get the Core Position (ClusterId * 4) + CoreId + GetCorePositionInStack(r0, r5, r1) + // The stack starts at the top of the stack region. Add '1' to the Core Position to get the top of the stack + add r0, r0, #1 + + // Get the base of the stack for the secondary cores + LoadConstantToReg (FixedPcdGet32(PcdCPUCoresSecStackBase), r1) + LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecPrimaryStackSize), r2) + add r1, r1, r2 + + // StackOffset = CorePos * StackSize + mul r0, r0, r2 + // SP = StackBase + StackOffset + add sp, r1, r0 + + +_PrepareArguments: + // Move sec startup address into a data register + // Ensure we're jumping to FV version of the code (not boot remapped alias) ldr r3, StartupAddr - # Move the CoreId in r0 to be the first argument of the SEC Entry Point + // Jump to SEC C code + // r0 = mp_id mov r0, r5 - - # jump to SEC C code - # r0 = core_id - blx r3 - - + blx r3 + +_NeverReturn: + b _NeverReturn diff --git a/ArmPlatformPkg/Sec/SecEntryPoint.asm b/ArmPlatformPkg/Sec/SecEntryPoint.asm index e85d6ce609..c39b80a85f 100644 --- a/ArmPlatformPkg/Sec/SecEntryPoint.asm +++ b/ArmPlatformPkg/Sec/SecEntryPoint.asm @@ -71,32 +71,57 @@ _WaitForEnabledScu bl ArmIsScuEnable tst r1, #1 beq _WaitForEnabledScu - b _SetupStack + b _SetupSecondaryCoreStack #endif _InitMem // Initialize Init Boot Memory bl ArmPlatformInitializeBootMemory - - // Only Primary CPU could run this line (the secondary cores have jumped from _IdentifyCpu to _SetupStack) - mov r5, #0 - -_SetupStack - // Setup Stack for the 4 CPU cores - //Read Stack Base address from PCD - LoadConstantToReg (FixedPcdGet32(PcdCPUCoresSecStackBase), r1) - - // Read Stack size from PCD - LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecStackSize), r2) - - // Calcuate Stack Pointer reg value using Stack size and CPU ID. - mov r3,r5 // r3 = core_id - mul r3,r3,r2 // r3 = core_id * stack_size = offset from the stack base - add r3,r3,r1 // r3 = stack_base + offset - mov sp, r3 + // Only Primary CPU could run this line (the secondary cores have jumped from _IdentifyCpu to _SetupStack) + LoadConstantToReg (FixedPcdGet32(PcdArmPrimaryCore), r5) + +_SetupPrimaryCoreStack + LoadConstantToReg (FixedPcdGet32(PcdCPUCoresSecStackBase), r2) + LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecPrimaryStackSize), r3) + // Calculate the Top of the Stack + add r2, r2, r3 + LoadConstantToReg (FixedPcdGet32(PcdSecGlobalVariableSize), r3) + + // The reserved space for global variable must be 8-bytes aligned for pushing + // 64-bit variable on the stack + SetPrimaryStack (r2, r3, r1) + + // Set all the SEC global variables to 0 + mov r3, sp + mov r1, #0x0 +_InitGlobals + str r1, [r3], #4 + cmp r3, r2 + blt _InitGlobals + + b _PrepareArguments + +_SetupSecondaryCoreStack + // Get the Core Position (ClusterId * 4) + CoreId + GetCorePositionInStack(r0, r5, r1) + // The stack starts at the top of the stack region. Add '1' to the Core Position to get the top of the stack + add r0, r0, #1 + + // Get the base of the stack for the secondary cores + LoadConstantToReg (FixedPcdGet32(PcdCPUCoresSecStackBase), r1) + LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecSecondaryStackSize), r2) + add r1, r1, r2 + + // StackOffset = CorePos * StackSize + mul r0, r0, r2 + // SP = StackBase + StackOffset + add sp, r1, r0 + + +_PrepareArguments // Move sec startup address into a data register - // ensure we're jumping to FV version of the code (not boot remapped alias) + // Ensure we're jumping to FV version of the code (not boot remapped alias) ldr r3, StartupAddr // Jump to SEC C code @@ -104,4 +129,6 @@ _SetupStack mov r0, r5 blx r3 +_NeverReturn + b _NeverReturn END