summaryrefslogtreecommitdiff
path: root/Silicon/AMD/Styx/Drivers/MpBootDxe
diff options
context:
space:
mode:
Diffstat (limited to 'Silicon/AMD/Styx/Drivers/MpBootDxe')
-rw-r--r--Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootDxe.c170
-rw-r--r--Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootDxe.inf53
-rw-r--r--Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootHelper.S87
3 files changed, 310 insertions, 0 deletions
diff --git a/Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootDxe.c b/Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootDxe.c
new file mode 100644
index 0000000000..bd7244648a
--- /dev/null
+++ b/Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootDxe.c
@@ -0,0 +1,170 @@
+/** @file
+
+ Copyright (c) 2016, AMD Inc. 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
+ 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 <Library/ArmLib.h>
+#include <Library/ArmSmcLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Guid/ArmMpCoreInfo.h>
+#include <Protocol/AmdMpBoot.h>
+
+
+/* These externs are used to relocate our Pen code into pre-allocated memory */
+extern VOID *SecondariesPenStart;
+extern VOID *SecondariesPenEnd;
+extern UINTN *AsmParkingBase;
+extern UINTN *AsmMailboxBase;
+
+
+STATIC
+EFI_PHYSICAL_ADDRESS
+ConfigurePen (
+ IN EFI_PHYSICAL_ADDRESS MpParkingBase,
+ IN UINTN MpParkingSize,
+ IN ARM_CORE_INFO *ArmCoreInfoTable,
+ IN UINTN ArmCoreCount
+ )
+{
+ EFI_PHYSICAL_ADDRESS PenBase;
+ UINTN PenSize;
+ UINTN MailboxBase;
+ UINTN CoreNum;
+ UINTN CoreMailbox;
+ UINTN CoreParking;
+
+ //
+ // Set Pen at the 2K-offset of the Parking area, skipping an 8-byte slot for the Core#.
+ // For details, refer to the "Multi-processor Startup for ARM Platforms" document:
+ // https://acpica.org/sites/acpica/files/MP%20Startup%20for%20ARM%20platforms.docx
+ //
+ PenBase = (EFI_PHYSICAL_ADDRESS)((UINTN)MpParkingBase + SIZE_2KB + sizeof(UINT64));
+ PenSize = (UINTN)&SecondariesPenEnd - (UINTN)&SecondariesPenStart;
+
+ // Relocate the Pen code
+ CopyMem ((VOID*)(PenBase), (VOID*)&SecondariesPenStart, PenSize);
+
+ // Put spin-table mailboxes below the pen code so we know where they are relative to code.
+ // Make sure this is 8 byte aligned.
+ MailboxBase = (UINTN)PenBase + ((UINTN)&SecondariesPenEnd - (UINTN)&SecondariesPenStart);
+ if (MailboxBase % sizeof(UINT64) != 0) {
+ MailboxBase += sizeof(UINT64) - MailboxBase % sizeof(UINT64);
+ }
+
+ // Update variables used in the Pen code
+ *(UINTN*)(PenBase + ((UINTN)&AsmMailboxBase - (UINTN)&SecondariesPenStart)) = MailboxBase;
+ *(UINTN*)(PenBase + ((UINTN)&AsmParkingBase - (UINTN)&SecondariesPenStart)) = (UINTN)MpParkingBase;
+
+ for (CoreNum = 0; CoreNum < ArmCoreCount; CoreNum++) {
+ // Clear the jump address at spin-table slot
+ CoreMailbox = MailboxBase + CoreNum * sizeof (UINT64);
+ *((UINTN*)(CoreMailbox)) = 0x0;
+
+ // Clear the jump address and set Core# at mp-parking slot
+ CoreParking = (UINTN)MpParkingBase + CoreNum * SIZE_4KB;
+ *((UINTN*)(CoreParking + sizeof (UINT64))) = 0x0;
+ *((UINTN*)(CoreParking + SIZE_2KB)) = CoreNum;
+
+ // Update table entry to be consumed by FDT parser
+ ArmCoreInfoTable[CoreNum].MailboxSetAddress = CoreMailbox;
+ }
+
+ // flush the cache before launching secondary cores
+ WriteBackDataCacheRange ((VOID *)MpParkingBase, MpParkingSize);
+
+ return PenBase;
+}
+
+
+EFI_STATUS
+EFIAPI
+MpBootDxeEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ AMD_MP_BOOT_PROTOCOL *MpBootProtocol;
+ EFI_PHYSICAL_ADDRESS MpParkingBase;
+ UINTN MpParkingSize;
+ ARM_CORE_INFO *ArmCoreInfoTable;
+ UINTN ArmCoreCount;
+ UINTN CoreNum;
+ EFI_PHYSICAL_ADDRESS PenBase;
+
+ DEBUG ((EFI_D_ERROR, "MpBootDxe Loaded\n"));
+
+ MpBootProtocol = NULL;
+ Status = gBS->LocateProtocol (
+ &gAmdMpBootProtocolGuid,
+ NULL,
+ (VOID **)&MpBootProtocol
+ );
+ if (EFI_ERROR (Status) || MpBootProtocol == NULL) {
+ DEBUG ((EFI_D_ERROR, "Warning: Failed to locate MP-Boot Protocol.\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((VOID *)MpBootProtocol->MpBootInfo == NULL) {
+ DEBUG ((EFI_D_ERROR, "Warning: MpBootInfo not allocated.\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ MpParkingBase = MpBootProtocol->MpBootInfo->MpParkingBase;
+ if ((VOID *)MpParkingBase == NULL) {
+ DEBUG ((EFI_D_ERROR, "Warning: MpParkingBase not allocated.\n"));
+ return EFI_UNSUPPORTED;
+ }
+ if (((UINTN)MpParkingBase & (SIZE_4KB -1)) != 0) {
+ DEBUG ((EFI_D_ERROR, "Warning: MpParkingBase not 4K aligned.\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ ArmCoreInfoTable = MpBootProtocol->MpBootInfo->ArmCoreInfoTable;
+ if (ArmCoreInfoTable == NULL) {
+ DEBUG ((EFI_D_ERROR, "Warning: ArmCoreInfoTable not allocated.\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ ArmCoreCount = MpBootProtocol->MpBootInfo->ArmCoreCount;
+ if (ArmCoreCount < 2) {
+ DEBUG ((EFI_D_ERROR, "Warning: Found %d cores.\n", ArmCoreCount));
+ return EFI_UNSUPPORTED;
+ }
+
+ MpParkingSize = ArmCoreCount * SIZE_4KB;
+ if (MpParkingSize > MpBootProtocol->MpBootInfo->MpParkingSize) {
+ DEBUG ((EFI_D_ERROR, "Warning: MpParkingSize = 0x%lX, not large enough for %d cores.\n",
+ MpBootProtocol->MpBootInfo->MpParkingSize, ArmCoreCount));
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((VOID *)MpBootProtocol->ParkSecondaryCore == NULL) {
+ DEBUG ((EFI_D_ERROR, "Warning: ParkSecondaryCore() not supported.\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ // Move secondary cores to our new Pen
+ PenBase = ConfigurePen (MpParkingBase, MpParkingSize, ArmCoreInfoTable, ArmCoreCount);
+ for (CoreNum = 0; CoreNum < ArmCoreCount; CoreNum++) {
+ MpBootProtocol->ParkSecondaryCore (&ArmCoreInfoTable[CoreNum], PenBase);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
diff --git a/Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootDxe.inf b/Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootDxe.inf
new file mode 100644
index 0000000000..ec63cd36e8
--- /dev/null
+++ b/Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootDxe.inf
@@ -0,0 +1,53 @@
+#/* @file
+#
+# Copyright (c) 2016, AMD Inc. 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
+# 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 = MpBootDxe
+ FILE_GUID = ff3f9c9b-6d36-4787-9144-6b22acba5e9b
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = MpBootDxeEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = AARCH64
+#
+#
+
+[Sources.common]
+ MpBootDxe.c
+
+[Sources.AARCH64]
+ MpBootHelper.S
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+ Silicon/AMD/Styx/AmdModulePkg/AmdModulePkg.dec
+ Silicon/AMD/Styx/AmdStyx.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ CacheMaintenanceLib
+ BaseMemoryLib
+ DebugLib
+
+[Protocols]
+ gAmdMpBootProtocolGuid ## CONSUMED
+
+[Depex]
+ gAmdMpBootProtocolGuid
diff --git a/Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootHelper.S b/Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootHelper.S
new file mode 100644
index 0000000000..c16cc59a1e
--- /dev/null
+++ b/Silicon/AMD/Styx/Drivers/MpBootDxe/MpBootHelper.S
@@ -0,0 +1,87 @@
+//
+// Copyright (c) 2011-2013, ARM Limited. All rights reserved.
+// Copyright (c) 2014 - 2016, AMD Inc. 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
+// 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.
+//
+//**
+// Derived from:
+// ArmPkg/Library/BdsLib/AArch64/BdsLinuxLoaderHelper.S
+//
+//**
+
+/* Secondary core pens for AArch64 Linux booting.
+
+ This code is placed in Linux kernel memory and marked reserved. UEFI ensures
+ that the secondary cores get to this pen and the kernel can then start the
+ cores from here.
+ NOTE: This code must be self-contained.
+*/
+
+#include <Library/ArmLib.h>
+
+.text
+.align 3
+
+GCC_ASM_EXPORT(SecondariesPenStart)
+ASM_GLOBAL SecondariesPenEnd
+
+ASM_PFX(SecondariesPenStart):
+ // Registers x0-x3 are reserved for future use and should be set to zero.
+ mov x0, xzr
+ mov x1, xzr
+ mov x2, xzr
+ mov x3, xzr
+
+ mrs x4, mpidr_el1 // Get MPCore register
+ and x5, x4, #ARM_CORE_MASK // Get core number
+ and x4, x4, #ARM_CLUSTER_MASK // Get cluster number
+
+ add x4, x5, x4, LSR #7 // Add scaled cluster number to core number
+ mov x6, x4 // Save a copy to compute mp-parking offset
+
+ ldr x5, AsmMailboxBase // Get mailbox addr relative to PC
+ lsl x4, x4, 3 // Add 8-byte offset for this core
+ add x4, x4, x5 //
+
+ ldr x5, AsmParkingBase // Get mp-parking addr relative to PC
+ lsl x6, x6, 12 // Add 4K-byte offset for this core
+ add x6, x6, x5 //
+
+ mov x5, 1 // Get mp-parking id# at 2K offset
+ lsl x5, x5, 11 //
+ add x5, x5, x6 //
+ ldr x10, [x5] //
+
+1: ldr x5, [x4] // Load jump-addr from spin-table mailbox
+ cmp xzr, x5 // Has the value been set?
+ b.ne 4f // If so, break out of loop
+
+ ldr x5, [x6] // Load mp-parking id#
+ cmp w10, w5 // Is it my id?
+ b.ne 2f // If not, continue polling
+
+ ldr x5, [x6, 8] // Load jump-addr from mp-parking
+ cmp xzr, x5 // Has the value been set?
+ b.ne 3f // If so, break out of loop
+
+2: wfe // Wait a bit
+ b 1b // Wait over, check again
+
+3: str xzr, [x6, 8] // Clear to acknowledge
+ mov x0, x6 // Return mp-parking address
+4: br x5 // Jump to new addr
+
+.align 3 // Make sure the variable below is 8 byte aligned.
+ .global AsmParkingBase
+AsmParkingBase: .xword 0xdeaddeadbeefbeef
+ .global AsmMailboxBase
+AsmMailboxBase: .xword 0xdeaddeadbeefbeef
+
+SecondariesPenEnd: