CPU_INFO_IN_HOB CpuInfo;\r
UINT32 ApCount;\r
CPU_INFO_IN_HOB *CpuInfoInHob;\r
+ volatile UINT32 *StartupApSignal;\r
\r
ApCount = CpuMpData->CpuCount - 1;\r
CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob;\r
sizeof (CPU_INFO_IN_HOB)\r
);\r
CopyMem (&CpuInfoInHob[Index1], &CpuInfo, sizeof (CPU_INFO_IN_HOB));\r
+\r
+ //\r
+ // Also exchange the StartupApSignal.\r
+ //\r
+ StartupApSignal = CpuMpData->CpuData[Index3].StartupApSignal;\r
+ CpuMpData->CpuData[Index3].StartupApSignal =\r
+ CpuMpData->CpuData[Index1].StartupApSignal;\r
+ CpuMpData->CpuData[Index1].StartupApSignal = StartupApSignal;\r
}\r
}\r
\r
// Restore AP's volatile registers saved\r
//\r
RestoreVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters, TRUE);\r
+ } else {\r
+ //\r
+ // The CPU driver might not flush TLB for APs on spot after updating\r
+ // page attributes. AP in mwait loop mode needs to take care of it when\r
+ // woken up.\r
+ //\r
+ CpuFlushTlb ();\r
}\r
\r
if (GetApState (&CpuMpData->CpuData[ProcessorNumber]) == CpuStateReady) {\r
)\r
{\r
volatile MP_CPU_EXCHANGE_INFO *ExchangeInfo;\r
+ UINTN Size;\r
+ IA32_SEGMENT_DESCRIPTOR *Selector;\r
\r
ExchangeInfo = CpuMpData->MpCpuExchangeInfo;\r
ExchangeInfo->Lock = 0;\r
//\r
AsmReadGdtr ((IA32_DESCRIPTOR *) &ExchangeInfo->GdtrProfile);\r
AsmReadIdtr ((IA32_DESCRIPTOR *) &ExchangeInfo->IdtrProfile);\r
+\r
+ //\r
+ // Find a 32-bit code segment\r
+ //\r
+ Selector = (IA32_SEGMENT_DESCRIPTOR *)ExchangeInfo->GdtrProfile.Base;\r
+ Size = ExchangeInfo->GdtrProfile.Limit + 1;\r
+ while (Size > 0) {\r
+ if (Selector->Bits.L == 0 && Selector->Bits.Type >= 8) {\r
+ ExchangeInfo->ModeTransitionSegment =\r
+ (UINT16)((UINTN)Selector - ExchangeInfo->GdtrProfile.Base);\r
+ break;\r
+ }\r
+ Selector += 1;\r
+ Size -= sizeof (IA32_SEGMENT_DESCRIPTOR);\r
+ }\r
+\r
+ //\r
+ // Copy all 32-bit code and 64-bit code into memory with type of\r
+ // EfiBootServicesCode to avoid page fault if NX memory protection is enabled.\r
+ //\r
+ if (CpuMpData->WakeupBufferHigh != 0) {\r
+ Size = CpuMpData->AddressMap.RendezvousFunnelSize -\r
+ CpuMpData->AddressMap.ModeTransitionOffset;\r
+ CopyMem (\r
+ (VOID *)CpuMpData->WakeupBufferHigh,\r
+ CpuMpData->AddressMap.RendezvousFunnelAddress +\r
+ CpuMpData->AddressMap.ModeTransitionOffset,\r
+ Size\r
+ );\r
+\r
+ ExchangeInfo->ModeTransitionMemory = (UINT32)CpuMpData->WakeupBufferHigh;\r
+ } else {\r
+ ExchangeInfo->ModeTransitionMemory = (UINT32)\r
+ (ExchangeInfo->BufferStart + CpuMpData->AddressMap.ModeTransitionOffset);\r
+ }\r
+\r
+ ExchangeInfo->ModeHighMemory = ExchangeInfo->ModeTransitionMemory +\r
+ (UINT32)ExchangeInfo->ModeOffset -\r
+ (UINT32)CpuMpData->AddressMap.ModeTransitionOffset;\r
+ ExchangeInfo->ModeHighSegment = (UINT16)ExchangeInfo->CodeSegment;\r
}\r
\r
/**\r
CpuMpData->WakeupBuffer = GetWakeupBuffer (ApResetVectorSize);\r
CpuMpData->MpCpuExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN)\r
(CpuMpData->WakeupBuffer + CpuMpData->AddressMap.RendezvousFunnelSize);\r
+ CpuMpData->WakeupBufferHigh = GetModeTransitionBuffer (\r
+ CpuMpData->AddressMap.RendezvousFunnelSize -\r
+ CpuMpData->AddressMap.ModeTransitionOffset\r
+ );\r
}\r
BackupAndPrepareWakeupBuffer (CpuMpData);\r
}\r
//\r
// Set BSP basic information\r
//\r
- InitializeApData (CpuMpData, 0, 0, CpuMpData->Buffer);\r
+ InitializeApData (CpuMpData, 0, 0, CpuMpData->Buffer + ApStackSize);\r
//\r
// Save assembly code information\r
//\r
ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);\r
ApicBaseMsr.Bits.BSP = 1;\r
AsmWriteMsr64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64);\r
+ ProgramVirtualWireMode ();\r
\r
//\r
// Wait for old BSP finished AP task\r