UefiCpuPkg MpInitLib: Save/restore original WakeupBuffer for DxeMpLib

Current code always allocates/frees < 1MB WakeupBuffer for DxeMpLib
until ExitBootService, but the allocation may be failed at late
phase of the boot.

This patch is to always save/restore original WakeupBuffer for
DxeMpLib, it is aligned with the solution for PeiMpLib at
9293d6e42e, then AllocateResetVector()
and FreeResetVector() will be common and moved to MpLib.c.
Only difference is GetWakeupBuffer() that will be in PeiMpLib or
DxeMpLib respectively.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Jeff Fan <jeff.fan@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
This commit is contained in:
Star Zeng 2017-08-04 10:05:20 +08:00
parent 4ad5f59715
commit a6b3d753f9
4 changed files with 109 additions and 168 deletions

View File

@ -75,72 +75,41 @@ SaveCpuMpData (
} }
/** /**
Allocate reset vector buffer. Get available system memory below 1MB by specified size.
@param[in, out] CpuMpData The pointer to CPU MP Data structure. @param[in] WakeupBufferSize Wakeup buffer size required
@retval other Return wakeup buffer address below 1MB.
@retval -1 Cannot find free memory below 1MB.
**/ **/
VOID UINTN
AllocateResetVector ( GetWakeupBuffer (
IN OUT CPU_MP_DATA *CpuMpData IN UINTN WakeupBufferSize
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
UINTN ApResetVectorSize;
EFI_PHYSICAL_ADDRESS StartAddress; EFI_PHYSICAL_ADDRESS StartAddress;
if (CpuMpData->SaveRestoreFlag) {
BackupAndPrepareWakeupBuffer (CpuMpData);
} else {
ApResetVectorSize = CpuMpData->AddressMap.RendezvousFunnelSize +
sizeof (MP_CPU_EXCHANGE_INFO);
StartAddress = BASE_1MB; StartAddress = BASE_1MB;
Status = gBS->AllocatePages ( Status = gBS->AllocatePages (
AllocateMaxAddress, AllocateMaxAddress,
EfiACPIMemoryNVS, EfiBootServicesData,
EFI_SIZE_TO_PAGES (ApResetVectorSize), EFI_SIZE_TO_PAGES (WakeupBufferSize),
&StartAddress &StartAddress
); );
ASSERT_EFI_ERROR (Status); ASSERT_EFI_ERROR (Status);
if (!EFI_ERROR (Status)) {
CpuMpData->WakeupBuffer = (UINTN) StartAddress;
CpuMpData->MpCpuExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN)
(CpuMpData->WakeupBuffer + CpuMpData->AddressMap.RendezvousFunnelSize);
//
// copy AP reset code in it
//
CopyMem (
(VOID *) CpuMpData->WakeupBuffer,
(VOID *) CpuMpData->AddressMap.RendezvousFunnelAddress,
CpuMpData->AddressMap.RendezvousFunnelSize
);
}
}
/**
Free AP reset vector buffer.
@param[in] CpuMpData The pointer to CPU MP Data structure.
**/
VOID
FreeResetVector (
IN CPU_MP_DATA *CpuMpData
)
{
EFI_STATUS Status;
UINTN ApResetVectorSize;
if (CpuMpData->SaveRestoreFlag) {
RestoreWakeupBuffer (CpuMpData);
} else {
ApResetVectorSize = CpuMpData->AddressMap.RendezvousFunnelSize +
sizeof (MP_CPU_EXCHANGE_INFO);
Status = gBS->FreePages( Status = gBS->FreePages(
(EFI_PHYSICAL_ADDRESS)CpuMpData->WakeupBuffer, StartAddress,
EFI_SIZE_TO_PAGES (ApResetVectorSize) EFI_SIZE_TO_PAGES (WakeupBufferSize)
); );
ASSERT_EFI_ERROR (Status); ASSERT_EFI_ERROR (Status);
DEBUG ((DEBUG_INFO, "WakeupBufferStart = %x, WakeupBufferSize = %x\n",
(UINTN) StartAddress, WakeupBufferSize));
} else {
StartAddress = (EFI_PHYSICAL_ADDRESS) -1;
} }
return (UINTN) StartAddress;
} }
/** /**
@ -299,7 +268,6 @@ MpInitChangeApLoopCallback (
CPU_MP_DATA *CpuMpData; CPU_MP_DATA *CpuMpData;
CpuMpData = GetCpuMpData (); CpuMpData = GetCpuMpData ();
CpuMpData->SaveRestoreFlag = TRUE;
CpuMpData->PmCodeSegment = GetProtectedModeCS (); CpuMpData->PmCodeSegment = GetProtectedModeCS ();
CpuMpData->ApLoopMode = PcdGet8 (PcdCpuApLoopMode); CpuMpData->ApLoopMode = PcdGet8 (PcdCpuApLoopMode);
mNumberToFinish = CpuMpData->CpuCount - 1; mNumberToFinish = CpuMpData->CpuCount - 1;

View File

@ -795,6 +795,81 @@ TimedWaitForApFinish (
IN UINT32 TimeLimit IN UINT32 TimeLimit
); );
/**
Get available system memory below 1MB by specified size.
@param[in] CpuMpData The pointer to CPU MP Data structure.
**/
VOID
BackupAndPrepareWakeupBuffer(
IN CPU_MP_DATA *CpuMpData
)
{
CopyMem (
(VOID *) CpuMpData->BackupBuffer,
(VOID *) CpuMpData->WakeupBuffer,
CpuMpData->BackupBufferSize
);
CopyMem (
(VOID *) CpuMpData->WakeupBuffer,
(VOID *) CpuMpData->AddressMap.RendezvousFunnelAddress,
CpuMpData->AddressMap.RendezvousFunnelSize
);
}
/**
Restore wakeup buffer data.
@param[in] CpuMpData The pointer to CPU MP Data structure.
**/
VOID
RestoreWakeupBuffer(
IN CPU_MP_DATA *CpuMpData
)
{
CopyMem (
(VOID *) CpuMpData->WakeupBuffer,
(VOID *) CpuMpData->BackupBuffer,
CpuMpData->BackupBufferSize
);
}
/**
Allocate reset vector buffer.
@param[in, out] CpuMpData The pointer to CPU MP Data structure.
**/
VOID
AllocateResetVector (
IN OUT CPU_MP_DATA *CpuMpData
)
{
UINTN ApResetVectorSize;
if (CpuMpData->WakeupBuffer == (UINTN) -1) {
ApResetVectorSize = CpuMpData->AddressMap.RendezvousFunnelSize +
sizeof (MP_CPU_EXCHANGE_INFO);
CpuMpData->WakeupBuffer = GetWakeupBuffer (ApResetVectorSize);
CpuMpData->MpCpuExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN)
(CpuMpData->WakeupBuffer + CpuMpData->AddressMap.RendezvousFunnelSize);
}
BackupAndPrepareWakeupBuffer (CpuMpData);
}
/**
Free AP reset vector buffer.
@param[in] CpuMpData The pointer to CPU MP Data structure.
**/
VOID
FreeResetVector (
IN CPU_MP_DATA *CpuMpData
)
{
RestoreWakeupBuffer (CpuMpData);
}
/** /**
This function will be called by BSP to wakeup AP. This function will be called by BSP to wakeup AP.
@ -1353,7 +1428,6 @@ MpInitLibInitialize (
CpuMpData->CpuApStackSize = ApStackSize; CpuMpData->CpuApStackSize = ApStackSize;
CpuMpData->BackupBuffer = BackupBufferAddr; CpuMpData->BackupBuffer = BackupBufferAddr;
CpuMpData->BackupBufferSize = ApResetVectorSize; CpuMpData->BackupBufferSize = ApResetVectorSize;
CpuMpData->SaveRestoreFlag = FALSE;
CpuMpData->WakeupBuffer = (UINTN) -1; CpuMpData->WakeupBuffer = (UINTN) -1;
CpuMpData->CpuCount = 1; CpuMpData->CpuCount = 1;
CpuMpData->BspNumber = 0; CpuMpData->BspNumber = 0;
@ -2120,41 +2194,3 @@ GetCpuMpDataFromGuidedHob (
return CpuMpData; return CpuMpData;
} }
/**
Get available system memory below 1MB by specified size.
@param[in] CpuMpData The pointer to CPU MP Data structure.
**/
VOID
BackupAndPrepareWakeupBuffer(
IN CPU_MP_DATA *CpuMpData
)
{
CopyMem (
(VOID *) CpuMpData->BackupBuffer,
(VOID *) CpuMpData->WakeupBuffer,
CpuMpData->BackupBufferSize
);
CopyMem (
(VOID *) CpuMpData->WakeupBuffer,
(VOID *) CpuMpData->AddressMap.RendezvousFunnelAddress,
CpuMpData->AddressMap.RendezvousFunnelSize
);
}
/**
Restore wakeup buffer data.
@param[in] CpuMpData The pointer to CPU MP Data structure.
**/
VOID
RestoreWakeupBuffer(
IN CPU_MP_DATA *CpuMpData
)
{
CopyMem (
(VOID *) CpuMpData->WakeupBuffer,
(VOID *) CpuMpData->BackupBuffer,
CpuMpData->BackupBufferSize
);
}

View File

@ -201,7 +201,6 @@ struct _CPU_MP_DATA {
UINTN WakeupBuffer; UINTN WakeupBuffer;
UINTN BackupBuffer; UINTN BackupBuffer;
UINTN BackupBufferSize; UINTN BackupBufferSize;
BOOLEAN SaveRestoreFlag;
volatile UINT32 StartCount; volatile UINT32 StartCount;
volatile UINT32 FinishedCount; volatile UINT32 FinishedCount;
@ -310,24 +309,18 @@ SaveCpuMpData (
IN CPU_MP_DATA *CpuMpData IN CPU_MP_DATA *CpuMpData
); );
/**
Allocate reset vector buffer.
@param[in, out] CpuMpData The pointer to CPU MP Data structure.
**/
VOID
AllocateResetVector (
IN OUT CPU_MP_DATA *CpuMpData
);
/** /**
Free AP reset vector buffer. Get available system memory below 1MB by specified size.
@param[in] CpuMpData The pointer to CPU MP Data structure. @param[in] WakeupBufferSize Wakeup buffer size required
@retval other Return wakeup buffer address below 1MB.
@retval -1 Cannot find free memory below 1MB.
**/ **/
VOID UINTN
FreeResetVector ( GetWakeupBuffer (
IN CPU_MP_DATA *CpuMpData IN UINTN WakeupBufferSize
); );
/** /**
@ -542,26 +535,6 @@ IsMwaitSupport (
VOID VOID
); );
/**
Get available system memory below 1MB by specified size.
@param[in] CpuMpData The pointer to CPU MP Data structure.
**/
VOID
BackupAndPrepareWakeupBuffer(
IN CPU_MP_DATA *CpuMpData
);
/**
Restore wakeup buffer data.
@param[in] CpuMpData The pointer to CPU MP Data structure.
**/
VOID
RestoreWakeupBuffer(
IN CPU_MP_DATA *CpuMpData
);
/** /**
Enable Debug Agent to support source debugging on AP function. Enable Debug Agent to support source debugging on AP function.

View File

@ -187,42 +187,6 @@ GetWakeupBuffer (
return (UINTN) -1; return (UINTN) -1;
} }
/**
Allocate reset vector buffer.
@param[in, out] CpuMpData The pointer to CPU MP Data structure.
**/
VOID
AllocateResetVector (
IN OUT CPU_MP_DATA *CpuMpData
)
{
UINTN ApResetVectorSize;
if (CpuMpData->WakeupBuffer == (UINTN) -1) {
ApResetVectorSize = CpuMpData->AddressMap.RendezvousFunnelSize +
sizeof (MP_CPU_EXCHANGE_INFO);
CpuMpData->WakeupBuffer = GetWakeupBuffer (ApResetVectorSize);
CpuMpData->MpCpuExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN)
(CpuMpData->WakeupBuffer + CpuMpData->AddressMap.RendezvousFunnelSize);
}
BackupAndPrepareWakeupBuffer (CpuMpData);
}
/**
Free AP reset vector buffer.
@param[in] CpuMpData The pointer to CPU MP Data structure.
**/
VOID
FreeResetVector (
IN CPU_MP_DATA *CpuMpData
)
{
RestoreWakeupBuffer (CpuMpData);
}
/** /**
Checks APs status and updates APs status if needed. Checks APs status and updates APs status if needed.