2 Implementation of SMM CPU Services Protocol.
4 Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "PiSmmCpuDxeSmm.h"
12 // SMM CPU Service Protocol instance
14 EFI_SMM_CPU_SERVICE_PROTOCOL mSmmCpuService
= {
20 SmmRegisterExceptionHandler
24 Gets processor information on the requested processor at the instant this call is made.
26 @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
27 @param[in] ProcessorNumber The handle number of processor.
28 @param[out] ProcessorInfoBuffer A pointer to the buffer where information for
29 the requested processor is deposited.
31 @retval EFI_SUCCESS Processor information was returned.
32 @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
33 @retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
34 @retval EFI_NOT_FOUND The processor with the handle specified by
35 ProcessorNumber does not exist in the platform.
41 IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL
*This
,
42 IN UINTN ProcessorNumber
,
43 OUT EFI_PROCESSOR_INFORMATION
*ProcessorInfoBuffer
49 if (ProcessorNumber
>= mMaxNumberOfCpus
|| ProcessorInfoBuffer
== NULL
) {
50 return EFI_INVALID_PARAMETER
;
53 if (gSmmCpuPrivate
->ProcessorInfo
[ProcessorNumber
].ProcessorId
== INVALID_APIC_ID
) {
58 // Fill in processor information
60 CopyMem (ProcessorInfoBuffer
, &gSmmCpuPrivate
->ProcessorInfo
[ProcessorNumber
], sizeof (EFI_PROCESSOR_INFORMATION
));
65 This service switches the requested AP to be the BSP since the next SMI.
67 @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
68 @param[in] ProcessorNumber The handle number of AP that is to become the new BSP.
70 @retval EFI_SUCCESS BSP will be switched in next SMI.
71 @retval EFI_UNSUPPORTED Switching the BSP or a processor to be hot-removed is not supported.
72 @retval EFI_NOT_FOUND The processor with the handle specified by ProcessorNumber does not exist.
73 @retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
78 IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL
*This
,
79 IN UINTN ProcessorNumber
85 if (ProcessorNumber
>= mMaxNumberOfCpus
) {
86 return EFI_INVALID_PARAMETER
;
89 if (gSmmCpuPrivate
->ProcessorInfo
[ProcessorNumber
].ProcessorId
== INVALID_APIC_ID
) {
93 if (gSmmCpuPrivate
->Operation
[ProcessorNumber
] != SmmCpuNone
||
94 gSmst
->CurrentlyExecutingCpu
== ProcessorNumber
) {
95 return EFI_UNSUPPORTED
;
99 // Setting of the BSP for next SMI is pending until all SMI handlers are finished
101 gSmmCpuPrivate
->Operation
[ProcessorNumber
] = SmmCpuSwitchBsp
;
106 Notify that a processor was hot-added.
108 @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
109 @param[in] ProcessorId Local APIC ID of the hot-added processor.
110 @param[out] ProcessorNumber The handle number of the hot-added processor.
112 @retval EFI_SUCCESS The hot-addition of the specified processors was successfully notified.
113 @retval EFI_UNSUPPORTED Hot addition of processor is not supported.
114 @retval EFI_NOT_FOUND The processor with the handle specified by ProcessorNumber does not exist.
115 @retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
116 @retval EFI_ALREADY_STARTED The processor is already online in the system.
121 IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL
*This
,
122 IN UINT64 ProcessorId
,
123 OUT UINTN
*ProcessorNumber
128 if (!FeaturePcdGet (PcdCpuHotPlugSupport
)) {
129 return EFI_UNSUPPORTED
;
135 if (ProcessorNumber
== NULL
|| ProcessorId
== INVALID_APIC_ID
) {
136 return EFI_INVALID_PARAMETER
;
140 // Check if the processor already exists
143 for (Index
= 0; Index
< mMaxNumberOfCpus
; Index
++) {
144 if (gSmmCpuPrivate
->ProcessorInfo
[Index
].ProcessorId
== ProcessorId
) {
145 return EFI_ALREADY_STARTED
;
150 // Check CPU hot plug data. The CPU RAS handler should have created the mapping
151 // of the APIC ID to SMBASE.
153 for (Index
= 0; Index
< mMaxNumberOfCpus
; Index
++) {
154 if (mCpuHotPlugData
.ApicId
[Index
] == ProcessorId
&&
155 gSmmCpuPrivate
->ProcessorInfo
[Index
].ProcessorId
== INVALID_APIC_ID
) {
156 gSmmCpuPrivate
->ProcessorInfo
[Index
].ProcessorId
= ProcessorId
;
157 gSmmCpuPrivate
->ProcessorInfo
[Index
].StatusFlag
= 0;
158 GetProcessorLocationByApicId (
160 &gSmmCpuPrivate
->ProcessorInfo
[Index
].Location
.Package
,
161 &gSmmCpuPrivate
->ProcessorInfo
[Index
].Location
.Core
,
162 &gSmmCpuPrivate
->ProcessorInfo
[Index
].Location
.Thread
165 *ProcessorNumber
= Index
;
166 gSmmCpuPrivate
->Operation
[Index
] = SmmCpuAdd
;
171 return EFI_INVALID_PARAMETER
;
175 Notify that a processor was hot-removed.
177 @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
178 @param[in] ProcessorNumber The handle number of the hot-added processor.
180 @retval EFI_SUCCESS The hot-removal of the specified processors was successfully notified.
181 @retval EFI_UNSUPPORTED Hot removal of processor is not supported.
182 @retval EFI_UNSUPPORTED Hot removal of BSP is not supported.
183 @retval EFI_UNSUPPORTED Hot removal of a processor with pending hot-plug operation is not supported.
184 @retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
189 IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL
*This
,
190 IN UINTN ProcessorNumber
193 if (!FeaturePcdGet (PcdCpuHotPlugSupport
)) {
194 return EFI_UNSUPPORTED
;
200 if (ProcessorNumber
>= mMaxNumberOfCpus
||
201 gSmmCpuPrivate
->ProcessorInfo
[ProcessorNumber
].ProcessorId
== INVALID_APIC_ID
) {
202 return EFI_INVALID_PARAMETER
;
208 if (ProcessorNumber
== gSmmCpuPrivate
->SmmCoreEntryContext
.CurrentlyExecutingCpu
) {
209 return EFI_UNSUPPORTED
;
212 if (gSmmCpuPrivate
->Operation
[ProcessorNumber
] != SmmCpuNone
) {
213 return EFI_UNSUPPORTED
;
216 gSmmCpuPrivate
->ProcessorInfo
[ProcessorNumber
].ProcessorId
= INVALID_APIC_ID
;
217 mCpuHotPlugData
.ApicId
[ProcessorNumber
] = INVALID_APIC_ID
;
220 // Removal of the processor from the CPU list is pending until all SMI handlers are finished
222 gSmmCpuPrivate
->Operation
[ProcessorNumber
] = SmmCpuRemove
;
227 This return the handle number for the calling processor.
229 @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
230 @param[out] ProcessorNumber The handle number of currently executing processor.
232 @retval EFI_SUCCESS The current processor handle number was returned
234 @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
240 IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL
*This
,
241 OUT UINTN
*ProcessorNumber
250 if (ProcessorNumber
== NULL
) {
251 return EFI_INVALID_PARAMETER
;
254 ApicId
= GetApicId ();
256 for (Index
= 0; Index
< mMaxNumberOfCpus
; Index
++) {
257 if (gSmmCpuPrivate
->ProcessorInfo
[Index
].ProcessorId
== ApicId
) {
258 *ProcessorNumber
= Index
;
263 // This should not happen
266 return EFI_NOT_FOUND
;
270 Update the SMM CPU list per the pending operation.
272 This function is called after return from SMI handlers.
282 // Handle pending BSP switch operations
284 for (Index
= 0; Index
< mMaxNumberOfCpus
; Index
++) {
285 if (gSmmCpuPrivate
->Operation
[Index
] == SmmCpuSwitchBsp
) {
286 gSmmCpuPrivate
->Operation
[Index
] = SmmCpuNone
;
287 mSmmMpSyncData
->SwitchBsp
= TRUE
;
288 mSmmMpSyncData
->CandidateBsp
[Index
] = TRUE
;
293 // Handle pending hot-add operations
295 for (Index
= 0; Index
< mMaxNumberOfCpus
; Index
++) {
296 if (gSmmCpuPrivate
->Operation
[Index
] == SmmCpuAdd
) {
297 gSmmCpuPrivate
->Operation
[Index
] = SmmCpuNone
;
303 // Handle pending hot-remove operations
305 for (Index
= 0; Index
< mMaxNumberOfCpus
; Index
++) {
306 if (gSmmCpuPrivate
->Operation
[Index
] == SmmCpuRemove
) {
307 gSmmCpuPrivate
->Operation
[Index
] = SmmCpuNone
;
314 Register exception handler.
316 @param This A pointer to the SMM_CPU_SERVICE_PROTOCOL instance.
317 @param ExceptionType Defines which interrupt or exception to hook. Type EFI_EXCEPTION_TYPE and
318 the valid values for this parameter are defined in EFI_DEBUG_SUPPORT_PROTOCOL
319 of the UEFI 2.0 specification.
320 @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER
321 that is called when a processor interrupt occurs.
322 If this parameter is NULL, then the handler will be uninstalled.
324 @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
325 @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was previously installed.
326 @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not previously installed.
327 @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
332 SmmRegisterExceptionHandler (
333 IN EFI_SMM_CPU_SERVICE_PROTOCOL
*This
,
334 IN EFI_EXCEPTION_TYPE ExceptionType
,
335 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
338 return RegisterCpuInterruptHandler (ExceptionType
, InterruptHandler
);
342 Initialize SMM CPU Services.
344 It installs EFI SMM CPU Services Protocol.
346 @param ImageHandle The firmware allocated handle for the EFI image.
348 @retval EFI_SUCCESS EFI SMM CPU Services Protocol was installed successfully.
351 InitializeSmmCpuServices (
357 Status
= gSmst
->SmmInstallProtocolInterface (
359 &gEfiSmmCpuServiceProtocolGuid
,
360 EFI_NATIVE_INTERFACE
,
363 ASSERT_EFI_ERROR (Status
);