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
))
96 return EFI_UNSUPPORTED
;
100 // Setting of the BSP for next SMI is pending until all SMI handlers are finished
102 gSmmCpuPrivate
->Operation
[ProcessorNumber
] = SmmCpuSwitchBsp
;
107 Notify that a processor was hot-added.
109 @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
110 @param[in] ProcessorId Local APIC ID of the hot-added processor.
111 @param[out] ProcessorNumber The handle number of the hot-added processor.
113 @retval EFI_SUCCESS The hot-addition of the specified processors was successfully notified.
114 @retval EFI_UNSUPPORTED Hot addition of processor is not supported.
115 @retval EFI_NOT_FOUND The processor with the handle specified by ProcessorNumber does not exist.
116 @retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
117 @retval EFI_ALREADY_STARTED The processor is already online in the system.
122 IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL
*This
,
123 IN UINT64 ProcessorId
,
124 OUT UINTN
*ProcessorNumber
129 if (!FeaturePcdGet (PcdCpuHotPlugSupport
)) {
130 return EFI_UNSUPPORTED
;
136 if ((ProcessorNumber
== NULL
) || (ProcessorId
== INVALID_APIC_ID
)) {
137 return EFI_INVALID_PARAMETER
;
141 // Check if the processor already exists
144 for (Index
= 0; Index
< mMaxNumberOfCpus
; Index
++) {
145 if (gSmmCpuPrivate
->ProcessorInfo
[Index
].ProcessorId
== ProcessorId
) {
146 return EFI_ALREADY_STARTED
;
151 // Check CPU hot plug data. The CPU RAS handler should have created the mapping
152 // of the APIC ID to SMBASE.
154 for (Index
= 0; Index
< mMaxNumberOfCpus
; Index
++) {
155 if ((mCpuHotPlugData
.ApicId
[Index
] == ProcessorId
) &&
156 (gSmmCpuPrivate
->ProcessorInfo
[Index
].ProcessorId
== INVALID_APIC_ID
))
158 gSmmCpuPrivate
->ProcessorInfo
[Index
].ProcessorId
= ProcessorId
;
159 gSmmCpuPrivate
->ProcessorInfo
[Index
].StatusFlag
= 0;
160 GetProcessorLocationByApicId (
162 &gSmmCpuPrivate
->ProcessorInfo
[Index
].Location
.Package
,
163 &gSmmCpuPrivate
->ProcessorInfo
[Index
].Location
.Core
,
164 &gSmmCpuPrivate
->ProcessorInfo
[Index
].Location
.Thread
167 *ProcessorNumber
= Index
;
168 gSmmCpuPrivate
->Operation
[Index
] = SmmCpuAdd
;
173 return EFI_INVALID_PARAMETER
;
177 Notify that a processor was hot-removed.
179 @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
180 @param[in] ProcessorNumber The handle number of the hot-added processor.
182 @retval EFI_SUCCESS The hot-removal of the specified processors was successfully notified.
183 @retval EFI_UNSUPPORTED Hot removal of processor is not supported.
184 @retval EFI_UNSUPPORTED Hot removal of BSP is not supported.
185 @retval EFI_UNSUPPORTED Hot removal of a processor with pending hot-plug operation is not supported.
186 @retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
191 IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL
*This
,
192 IN UINTN ProcessorNumber
195 if (!FeaturePcdGet (PcdCpuHotPlugSupport
)) {
196 return EFI_UNSUPPORTED
;
202 if ((ProcessorNumber
>= mMaxNumberOfCpus
) ||
203 (gSmmCpuPrivate
->ProcessorInfo
[ProcessorNumber
].ProcessorId
== INVALID_APIC_ID
))
205 return EFI_INVALID_PARAMETER
;
211 if (ProcessorNumber
== gSmmCpuPrivate
->SmmCoreEntryContext
.CurrentlyExecutingCpu
) {
212 return EFI_UNSUPPORTED
;
215 if (gSmmCpuPrivate
->Operation
[ProcessorNumber
] != SmmCpuNone
) {
216 return EFI_UNSUPPORTED
;
219 gSmmCpuPrivate
->ProcessorInfo
[ProcessorNumber
].ProcessorId
= INVALID_APIC_ID
;
220 mCpuHotPlugData
.ApicId
[ProcessorNumber
] = INVALID_APIC_ID
;
223 // Removal of the processor from the CPU list is pending until all SMI handlers are finished
225 gSmmCpuPrivate
->Operation
[ProcessorNumber
] = SmmCpuRemove
;
230 This return the handle number for the calling processor.
232 @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
233 @param[out] ProcessorNumber The handle number of currently executing processor.
235 @retval EFI_SUCCESS The current processor handle number was returned
237 @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
243 IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL
*This
,
244 OUT UINTN
*ProcessorNumber
253 if (ProcessorNumber
== NULL
) {
254 return EFI_INVALID_PARAMETER
;
257 ApicId
= GetApicId ();
259 for (Index
= 0; Index
< mMaxNumberOfCpus
; Index
++) {
260 if (gSmmCpuPrivate
->ProcessorInfo
[Index
].ProcessorId
== ApicId
) {
261 *ProcessorNumber
= Index
;
267 // This should not happen
270 return EFI_NOT_FOUND
;
274 Update the SMM CPU list per the pending operation.
276 This function is called after return from SMI handlers.
286 // Handle pending BSP switch operations
288 for (Index
= 0; Index
< mMaxNumberOfCpus
; Index
++) {
289 if (gSmmCpuPrivate
->Operation
[Index
] == SmmCpuSwitchBsp
) {
290 gSmmCpuPrivate
->Operation
[Index
] = SmmCpuNone
;
291 mSmmMpSyncData
->SwitchBsp
= TRUE
;
292 mSmmMpSyncData
->CandidateBsp
[Index
] = TRUE
;
297 // Handle pending hot-add operations
299 for (Index
= 0; Index
< mMaxNumberOfCpus
; Index
++) {
300 if (gSmmCpuPrivate
->Operation
[Index
] == SmmCpuAdd
) {
301 gSmmCpuPrivate
->Operation
[Index
] = SmmCpuNone
;
307 // Handle pending hot-remove operations
309 for (Index
= 0; Index
< mMaxNumberOfCpus
; Index
++) {
310 if (gSmmCpuPrivate
->Operation
[Index
] == SmmCpuRemove
) {
311 gSmmCpuPrivate
->Operation
[Index
] = SmmCpuNone
;
318 Register exception handler.
320 @param This A pointer to the SMM_CPU_SERVICE_PROTOCOL instance.
321 @param ExceptionType Defines which interrupt or exception to hook. Type EFI_EXCEPTION_TYPE and
322 the valid values for this parameter are defined in EFI_DEBUG_SUPPORT_PROTOCOL
323 of the UEFI 2.0 specification.
324 @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER
325 that is called when a processor interrupt occurs.
326 If this parameter is NULL, then the handler will be uninstalled.
328 @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
329 @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was previously installed.
330 @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not previously installed.
331 @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
336 SmmRegisterExceptionHandler (
337 IN EFI_SMM_CPU_SERVICE_PROTOCOL
*This
,
338 IN EFI_EXCEPTION_TYPE ExceptionType
,
339 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
342 return RegisterCpuInterruptHandler (ExceptionType
, InterruptHandler
);
346 Initialize SMM CPU Services.
348 It installs EFI SMM CPU Services Protocol.
350 @param ImageHandle The firmware allocated handle for the EFI image.
352 @retval EFI_SUCCESS EFI SMM CPU Services Protocol was installed successfully.
355 InitializeSmmCpuServices (
361 Status
= gSmst
->SmmInstallProtocolInterface (
363 &gEfiSmmCpuServiceProtocolGuid
,
364 EFI_NATIVE_INTERFACE
,
367 ASSERT_EFI_ERROR (Status
);