UefiCpuPkg/MpInitLib: fix issue in wakeup buffer initialization

To fix an issue in which enabling NX feature will mark the AP wakeup
buffer as non-executable and fail the AP init, the buffer was split
into two part: the lower part in memory within 1MB and the higher part
within allocated executable memory (EfiBootServicesCode). But the
address of higher part memory was stored in lower part memory, which
is actually shared with legacy components and will be overwritten by
LegacyBiosDxe driver if CSM is enabled.

This patch fixes this issue by storing the address of higher part
memory in CpuMpData instead of ExchangeInfo.

Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jian J Wang <jian.j.wang@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
Jian J Wang 2018-01-24 09:36:01 +08:00 committed by Ruiyu Ni
parent c3492bd9bb
commit 66833b2a87
2 changed files with 11 additions and 10 deletions

View File

@ -823,19 +823,20 @@ FillExchangeInfoData (
// Copy all 32-bit code and 64-bit code into memory with type of
// EfiBootServicesCode to avoid page fault if NX memory protection is enabled.
//
if (ExchangeInfo->ModeTransitionMemory != 0) {
if (CpuMpData->WakeupBufferHigh != 0) {
Size = CpuMpData->AddressMap.RendezvousFunnelSize -
CpuMpData->AddressMap.ModeTransitionOffset;
CopyMem (
(VOID *)(UINTN)ExchangeInfo->ModeTransitionMemory,
(VOID *)CpuMpData->WakeupBufferHigh,
CpuMpData->AddressMap.RendezvousFunnelAddress +
CpuMpData->AddressMap.ModeTransitionOffset,
Size
);
ExchangeInfo->ModeHighMemory = ExchangeInfo->ModeTransitionMemory;
ExchangeInfo->ModeHighMemory += (UINT32)ExchangeInfo->ModeOffset -
(UINT32)CpuMpData->AddressMap.ModeTransitionOffset;
ExchangeInfo->ModeTransitionMemory = (UINT32)CpuMpData->WakeupBufferHigh;
ExchangeInfo->ModeHighMemory = (UINT32)CpuMpData->WakeupBufferHigh +
(UINT32)ExchangeInfo->ModeOffset -
(UINT32)CpuMpData->AddressMap.ModeTransitionOffset;
ExchangeInfo->ModeHighSegment = (UINT16)ExchangeInfo->CodeSegment;
} else {
ExchangeInfo->ModeTransitionMemory = (UINT32)
@ -916,11 +917,10 @@ AllocateResetVector (
CpuMpData->WakeupBuffer = GetWakeupBuffer (ApResetVectorSize);
CpuMpData->MpCpuExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN)
(CpuMpData->WakeupBuffer + CpuMpData->AddressMap.RendezvousFunnelSize);
CpuMpData->MpCpuExchangeInfo->ModeTransitionMemory = (UINT32)
GetModeTransitionBuffer (
CpuMpData->AddressMap.RendezvousFunnelSize -
CpuMpData->AddressMap.ModeTransitionOffset
);
CpuMpData->WakeupBufferHigh = GetModeTransitionBuffer (
CpuMpData->AddressMap.RendezvousFunnelSize -
CpuMpData->AddressMap.ModeTransitionOffset
);
}
BackupAndPrepareWakeupBuffer (CpuMpData);
}

View File

@ -208,6 +208,7 @@ struct _CPU_MP_DATA {
UINTN CpuApStackSize;
MP_ASSEMBLY_ADDRESS_MAP AddressMap;
UINTN WakeupBuffer;
UINTN WakeupBufferHigh;
UINTN BackupBuffer;
UINTN BackupBufferSize;