Location->Package = (InitialApicId >> (ThreadBits + CoreBits));\r
}\r
\r
+/**\r
+ Worker function for SwitchBSP().\r
+\r
+ Worker function for SwitchBSP(), assigned to the AP which is intended\r
+ to become BSP.\r
+\r
+ @param[in] Buffer Pointer to CPU MP Data\r
+**/\r
+VOID\r
+EFIAPI\r
+FutureBSPProc (\r
+ IN VOID *Buffer\r
+ )\r
+{\r
+ CPU_MP_DATA *DataInHob;\r
+\r
+ DataInHob = (CPU_MP_DATA *) Buffer;\r
+ AsmExchangeRole (&DataInHob->APInfo, &DataInHob->BSPInfo);\r
+}\r
+\r
/**\r
Get the Application Processors state.\r
\r
// Invoke AP function here\r
//\r
Procedure (Parameter);\r
- //\r
- // Re-get the CPU APICID and Initial APICID\r
- //\r
- CpuMpData->CpuData[ProcessorNumber].ApicId = GetApicId ();\r
- CpuMpData->CpuData[ProcessorNumber].InitialApicId = GetInitialApicId ();\r
+ if (CpuMpData->SwitchBspFlag) {\r
+ //\r
+ // Re-get the processor number due to BSP/AP maybe exchange in AP function\r
+ //\r
+ GetProcessorNumber (CpuMpData, &ProcessorNumber);\r
+ CpuMpData->CpuData[ProcessorNumber].ApFunction = 0;\r
+ CpuMpData->CpuData[ProcessorNumber].ApFunctionArgument = 0;\r
+ } else {\r
+ //\r
+ // Re-get the CPU APICID and Initial APICID\r
+ //\r
+ CpuMpData->CpuData[ProcessorNumber].ApicId = GetApicId ();\r
+ CpuMpData->CpuData[ProcessorNumber].InitialApicId = GetInitialApicId ();\r
+ }\r
}\r
SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateFinished);\r
}\r
CpuMpData->CpuCount = 1;\r
CpuMpData->BspNumber = 0;\r
CpuMpData->WaitEvent = NULL;\r
+ CpuMpData->SwitchBspFlag = FALSE;\r
CpuMpData->CpuData = (CPU_AP_DATA *) (CpuMpData + 1);\r
CpuMpData->CpuInfoInHob = (UINT64) (UINTN) (CpuMpData->CpuData + MaxLogicalProcessorNumber);\r
InitializeSpinLock(&CpuMpData->MpLock);\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Worker function to switch the requested AP to be the BSP from that point onward.\r
+\r
+ @param[in] ProcessorNumber The handle number of AP that is to become the new BSP.\r
+ @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an\r
+ enabled AP. Otherwise, it will be disabled.\r
+\r
+ @retval EFI_SUCCESS BSP successfully switched.\r
+ @retval others Failed to switch BSP. \r
+\r
+**/\r
+EFI_STATUS\r
+SwitchBSPWorker (\r
+ IN UINTN ProcessorNumber,\r
+ IN BOOLEAN EnableOldBSP\r
+ )\r
+{\r
+ CPU_MP_DATA *CpuMpData;\r
+ UINTN CallerNumber;\r
+ CPU_STATE State;\r
+ MSR_IA32_APIC_BASE_REGISTER ApicBaseMsr;\r
+\r
+ CpuMpData = GetCpuMpData ();\r
+\r
+ //\r
+ // Check whether caller processor is BSP\r
+ //\r
+ MpInitLibWhoAmI (&CallerNumber);\r
+ if (CallerNumber != CpuMpData->BspNumber) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (ProcessorNumber >= CpuMpData->CpuCount) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Check whether specified AP is disabled\r
+ //\r
+ State = GetApState (&CpuMpData->CpuData[ProcessorNumber]);\r
+ if (State == CpuStateDisabled) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check whether ProcessorNumber specifies the current BSP\r
+ //\r
+ if (ProcessorNumber == CpuMpData->BspNumber) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check whether specified AP is busy\r
+ //\r
+ if (State == CpuStateBusy) {\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ CpuMpData->BSPInfo.State = CPU_SWITCH_STATE_IDLE;\r
+ CpuMpData->APInfo.State = CPU_SWITCH_STATE_IDLE;\r
+ CpuMpData->SwitchBspFlag = TRUE;\r
+\r
+ //\r
+ // Clear the BSP bit of MSR_IA32_APIC_BASE\r
+ //\r
+ ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);\r
+ ApicBaseMsr.Bits.BSP = 0;\r
+ AsmWriteMsr64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64);\r
+\r
+ //\r
+ // Need to wakeUp AP (future BSP).\r
+ //\r
+ WakeUpAP (CpuMpData, FALSE, ProcessorNumber, FutureBSPProc, CpuMpData);\r
+\r
+ AsmExchangeRole (&CpuMpData->BSPInfo, &CpuMpData->APInfo);\r
+\r
+ //\r
+ // Set the BSP bit of MSR_IA32_APIC_BASE on new BSP\r
+ //\r
+ ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);\r
+ ApicBaseMsr.Bits.BSP = 1;\r
+ AsmWriteMsr64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64);\r
+\r
+ //\r
+ // Wait for old BSP finished AP task\r
+ //\r
+ while (GetApState (&CpuMpData->CpuData[CallerNumber]) != CpuStateFinished) {\r
+ CpuPause ();\r
+ }\r
+\r
+ CpuMpData->SwitchBspFlag = FALSE;\r
+ //\r
+ // Set old BSP enable state\r
+ //\r
+ if (!EnableOldBSP) {\r
+ SetApState (&CpuMpData->CpuData[CallerNumber], CpuStateDisabled);\r
+ }\r
+ //\r
+ // Save new BSP number\r
+ //\r
+ CpuMpData->BspNumber = (UINT32) ProcessorNumber;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
\r
/**\r
This return the handle number for the calling processor. This service may be\r
OUT UINTN *ProcessorNumber\r
)\r
{\r
- return EFI_UNSUPPORTED;\r
+ CPU_MP_DATA *CpuMpData;\r
+\r
+ if (ProcessorNumber == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ CpuMpData = GetCpuMpData ();\r
+\r
+ return GetProcessorNumber (CpuMpData, ProcessorNumber);\r
}\r
\r
/**\r