59STATIC APIC_ID *mPluggedApicIds;
60STATIC APIC_ID *mToUnplugApicIds;
61STATIC UINT32 *mToUnplugSelectors;
66STATIC UINT32 mPostSmmPenAddress;
96 IN APIC_ID *PluggedApicIds,
97 IN UINT32 PluggedCount
114 while (PluggedIdx < PluggedCount) {
117 UINTN NewProcessorNumberByProtocol;
119 NewApicId = PluggedApicIds[PluggedIdx];
125 CheckSlot < mCpuHotPlugData->ArrayLength;
128 if (mCpuHotPlugData->ApicId[CheckSlot] == NewApicId) {
133 if (CheckSlot < mCpuHotPlugData->ArrayLength) {
136 "%a: APIC ID " FMT_APIC_ID
" was hot-plugged "
137 "before; ignoring it\n",
148 while (NewSlot < mCpuHotPlugData->ArrayLength &&
149 mCpuHotPlugData->ApicId[NewSlot] != MAX_UINT64)
154 if (NewSlot == mCpuHotPlugData->ArrayLength) {
157 "%a: no room for APIC ID " FMT_APIC_ID
"\n",
161 return EFI_OUT_OF_RESOURCES;
167 mCpuHotPlugData->ApicId[NewSlot] = NewApicId;
174 mCpuHotPlugData->SmBase[NewSlot],
177 if (EFI_ERROR (Status)) {
184 Status = mMmCpuService->AddProcessor (
187 &NewProcessorNumberByProtocol
189 if (EFI_ERROR (Status)) {
192 "%a: AddProcessor(" FMT_APIC_ID
"): %r\n",
202 "%a: hot-added APIC ID " FMT_APIC_ID
", SMBASE 0x%Lx, "
203 "EFI_SMM_CPU_SERVICE_PROTOCOL assigned number %Lu\n",
206 (UINT64)mCpuHotPlugData->SmBase[NewSlot],
207 (UINT64)NewProcessorNumberByProtocol
220 mCpuHotPlugData->ApicId[NewSlot] = MAX_UINT64;
246 IsBsp = (BOOLEAN)(ApicBaseMsr.
Bits.
BSP == 1);
278 for (Idx = 0; Idx < mCpuHotEjectData->ArrayLength; Idx++) {
279 QemuSelector = mCpuHotEjectData->QemuSelectorMap[Idx];
281 if (QemuSelector != CPU_EJECT_QEMU_SELECTOR_INVALID) {
290 QemuCpuhpWriteCpuSelector (mMmCpuIo, (UINT32)QemuSelector);
291 QemuCpuhpWriteCpuStatus (mMmCpuIo, QEMU_CPUHP_STAT_EJECT);
306 mCpuHotEjectData->QemuSelectorMap[Idx] =
307 CPU_EJECT_QEMU_SELECTOR_INVALID;
311 "%a: Unplugged ProcessorNum %u, "
312 "QemuSelector %Lu\n",
328 mCpuHotEjectData->Handler =
NULL;
356 QemuSelector = mCpuHotEjectData->QemuSelectorMap[ProcessorNum];
357 if (QemuSelector == CPU_EJECT_QEMU_SELECTOR_INVALID) {
359 while (mCpuHotEjectData->Handler !=
NULL) {
414 IN APIC_ID *ToUnplugApicIds,
415 IN UINT32 *ToUnplugSelectors,
416 IN UINT32 ToUnplugCount
426 while (ToUnplugIdx < ToUnplugCount) {
427 APIC_ID RemoveApicId;
430 RemoveApicId = ToUnplugApicIds[ToUnplugIdx];
431 QemuSelector = ToUnplugSelectors[ToUnplugIdx];
445 for (ProcessorNum = 0;
446 ProcessorNum < mCpuHotPlugData->ArrayLength;
449 if (mCpuHotPlugData->ApicId[ProcessorNum] == RemoveApicId) {
457 if (ProcessorNum == mCpuHotPlugData->ArrayLength) {
460 "%a: did not find APIC ID " FMT_APIC_ID
472 Status = mMmCpuService->RemoveProcessor (mMmCpuService, ProcessorNum);
473 if (EFI_ERROR (Status)) {
476 "%a: RemoveProcessor(" FMT_APIC_ID
"): %r\n",
484 if (mCpuHotEjectData->QemuSelectorMap[ProcessorNum] !=
485 CPU_EJECT_QEMU_SELECTOR_INVALID)
499 "%a: ProcessorNum %Lu maps to QemuSelector %Lu, "
500 "cannot also map to %u\n",
502 (UINT64)ProcessorNum,
503 mCpuHotEjectData->QemuSelectorMap[ProcessorNum],
507 return EFI_ALREADY_STARTED;
513 mCpuHotEjectData->QemuSelectorMap[ProcessorNum] = (UINT64)QemuSelector;
517 "%a: Started hot-unplug on ProcessorNum %Lu, APIC ID "
518 FMT_APIC_ID
", QemuSelector %u\n",
520 (UINT64)ProcessorNum,
529 if (EjectCount != 0) {
533 mCpuHotEjectData->Handler =
EjectCpu;
607 IN CONST VOID *Context OPTIONAL,
608 IN OUT VOID *CommBuffer OPTIONAL,
615 UINT32 ToUnplugCount;
621 ASSERT (DispatchHandle == mDispatchHandle);
627 ASSERT (Context ==
NULL);
632 Status = mMmCpuIo->
Io.
Read (
639 if (EFI_ERROR (Status)) {
642 "%a: failed to read ICH9_APM_CNT: %r\n",
652 if (ApmControl != ICH9_APM_CNT_CPU_HOTPLUG) {
656 return EFI_WARN_INTERRUPT_SOURCE_QUIESCED;
664 mCpuHotPlugData->ArrayLength,
665 mCpuHotPlugData->ArrayLength - 1,
672 if (EFI_ERROR (Status)) {
676 if (PluggedCount > 0) {
678 if (EFI_ERROR (Status)) {
683 if (ToUnplugCount > 0) {
684 Status =
UnplugCpus (mToUnplugApicIds, mToUnplugSelectors, ToUnplugCount);
685 if (EFI_ERROR (Status)) {
727 if (!
PcdGetBool (PcdQ35SmramAtDefaultSmbase)) {
728 return EFI_UNSUPPORTED;
738 Status = gMmst->MmLocateProtocol (
739 &gEfiMmCpuIoProtocolGuid,
743 if (EFI_ERROR (Status)) {
744 DEBUG ((DEBUG_ERROR,
"%a: locate MmCpuIo: %r\n", __func__, Status));
748 Status = gMmst->MmLocateProtocol (
749 &gEfiSmmCpuServiceProtocolGuid,
751 (VOID **)&mMmCpuService
753 if (EFI_ERROR (Status)) {
756 "%a: locate MmCpuService: %r\n",
770 mCpuHotPlugData = (VOID *)(
UINTN)
PcdGet64 (PcdCpuHotPlugDataAddress);
771 mCpuHotEjectData = (VOID *)(
UINTN)
PcdGet64 (PcdCpuHotEjectDataAddress);
773 if (mCpuHotPlugData ==
NULL) {
774 Status = EFI_NOT_FOUND;
775 DEBUG ((DEBUG_ERROR,
"%a: CPU_HOT_PLUG_DATA: %r\n", __func__, Status));
782 if (mCpuHotPlugData->ArrayLength == 1) {
783 return EFI_UNSUPPORTED;
786 if (mCpuHotEjectData ==
NULL) {
787 Status = EFI_NOT_FOUND;
788 }
else if (mCpuHotPlugData->ArrayLength != mCpuHotEjectData->ArrayLength) {
789 Status = EFI_INVALID_PARAMETER;
794 if (EFI_ERROR (Status)) {
795 DEBUG ((DEBUG_ERROR,
"%a: CPU_HOT_EJECT_DATA: %r\n", __func__, Status));
806 Status = EFI_ABORTED;
807 DEBUG ((DEBUG_ERROR,
"%a: invalid CPU_HOT_PLUG_DATA\n", __func__));
814 (VOID **)&mPluggedApicIds
816 if (EFI_ERROR (Status)) {
817 DEBUG ((DEBUG_ERROR,
"%a: MmAllocatePool(): %r\n", __func__, Status));
824 (VOID **)&mToUnplugApicIds
826 if (EFI_ERROR (Status)) {
827 DEBUG ((DEBUG_ERROR,
"%a: MmAllocatePool(): %r\n", __func__, Status));
828 goto ReleasePluggedApicIds;
834 (VOID **)&mToUnplugSelectors
836 if (EFI_ERROR (Status)) {
837 DEBUG ((DEBUG_ERROR,
"%a: MmAllocatePool(): %r\n", __func__, Status));
838 goto ReleaseToUnplugApicIds;
846 SystemTable->BootServices
848 if (EFI_ERROR (Status)) {
849 goto ReleaseToUnplugSelectors;
874 QemuCpuhpWriteCpuSelector (mMmCpuIo, 0);
875 QemuCpuhpWriteCpuSelector (mMmCpuIo, 0);
876 QemuCpuhpWriteCommand (mMmCpuIo, QEMU_CPUHP_CMD_GET_PENDING);
877 if (QemuCpuhpReadCommandData2 (mMmCpuIo) != 0) {
878 Status = EFI_NOT_FOUND;
881 "%a: modern CPU hotplug interface: %r\n",
885 goto ReleasePostSmmPen;
891 Status = gMmst->MmiHandlerRegister (
896 if (EFI_ERROR (Status)) {
899 "%a: MmiHandlerRegister(): %r\n",
903 goto ReleasePostSmmPen;
915 mPostSmmPenAddress = 0;
917ReleaseToUnplugSelectors:
918 gMmst->MmFreePool (mToUnplugSelectors);
919 mToUnplugSelectors =
NULL;
921ReleaseToUnplugApicIds:
922 gMmst->MmFreePool (mToUnplugApicIds);
923 mToUnplugApicIds =
NULL;
925ReleasePluggedApicIds:
926 gMmst->MmFreePool (mPluggedApicIds);
927 mPluggedApicIds =
NULL;
VOID EFIAPI CpuDeadLoop(VOID)
VOID EFIAPI MemoryFence(VOID)
VOID EFIAPI CpuPause(VOID)
VOID EFIAPI DisableInterrupts(VOID)
VOID EFIAPI EjectCpu(IN UINTN ProcessorNum)
STATIC EFI_STATUS EFIAPI CpuHotplugMmi(IN EFI_HANDLE DispatchHandle, IN CONST VOID *Context OPTIONAL, IN OUT VOID *CommBuffer OPTIONAL, IN OUT UINTN *CommBufferSize OPTIONAL)
STATIC EFI_STATUS ProcessHotAddedCpus(IN APIC_ID *PluggedApicIds, IN UINT32 PluggedCount)
STATIC EFI_STATUS UnplugCpus(IN APIC_ID *ToUnplugApicIds, IN UINT32 *ToUnplugSelectors, IN UINT32 ToUnplugCount)
STATIC BOOLEAN CheckIfBsp(VOID)
VOID EFIAPI CpuSleep(VOID)
UINT64 EFIAPI AsmReadMsr64(IN UINT32 Index)
#define RETURN_ERROR(StatusCode)
#define DEBUG(Expression)
#define MSR_IA32_APIC_BASE
#define PcdGet64(TokenName)
#define PcdGetBool(TokenName)
#define FeaturePcdGet(TokenName)
#define EFI_INTERRUPT_PENDING
EFI_STATUS QemuCpuhpCollectApicIds(IN CONST EFI_MM_CPU_IO_PROTOCOL *MmCpuIo, IN UINT32 PossibleCpuCount, IN UINT32 ApicIdCount, OUT APIC_ID *PluggedApicIds, OUT UINT32 *PluggedCount, OUT APIC_ID *ToUnplugApicIds, OUT UINT32 *ToUnplugSelectors, OUT UINT32 *ToUnplugCount)
RETURN_STATUS EFIAPI SafeUintnMult(IN UINTN Multiplicand, IN UINTN Multiplier, OUT UINTN *Result)
RETURN_STATUS EFIAPI SafeUintnSub(IN UINTN Minuend, IN UINTN Subtrahend, OUT UINTN *Result)
EFI_STATUS SmbaseAllocatePostSmmPen(OUT UINT32 *PenAddress, IN CONST EFI_BOOT_SERVICES *BootServices)
VOID SmbaseInstallFirstSmiHandler(VOID)
VOID SmbaseReinstallPostSmmPen(IN UINT32 PenAddress)
VOID SmbaseReleasePostSmmPen(IN UINT32 PenAddress, IN CONST EFI_BOOT_SERVICES *BootServices)
EFI_STATUS SmbaseRelocate(IN APIC_ID ApicId, IN UINTN Smbase, IN UINT32 PenAddress)
EFI_ALLOCATE_POOL MmAllocatePool
struct MSR_IA32_APIC_BASE_REGISTER::@627 Bits