2 Implementation of SMM CPU Services Protocol.
4 Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "PiSmmCpuDxeSmm.h"
18 // SMM CPU Service Protocol instance
20 EFI_SMM_CPU_SERVICE_PROTOCOL mSmmCpuService
= {
26 SmmRegisterExceptionHandler
30 Gets processor information on the requested processor at the instant this call is made.
32 @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
33 @param[in] ProcessorNumber The handle number of processor.
34 @param[out] ProcessorInfoBuffer A pointer to the buffer where information for
35 the requested processor is deposited.
37 @retval EFI_SUCCESS Processor information was returned.
38 @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
39 @retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
40 @retval EFI_NOT_FOUND The processor with the handle specified by
41 ProcessorNumber does not exist in the platform.
47 IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL
*This
,
48 IN UINTN ProcessorNumber
,
49 OUT EFI_PROCESSOR_INFORMATION
*ProcessorInfoBuffer
55 if (ProcessorNumber
>= mMaxNumberOfCpus
|| ProcessorInfoBuffer
== NULL
) {
56 return EFI_INVALID_PARAMETER
;
59 if (gSmmCpuPrivate
->ProcessorInfo
[ProcessorNumber
].ProcessorId
== INVALID_APIC_ID
) {
64 // Fill in processor information
66 CopyMem (ProcessorInfoBuffer
, &gSmmCpuPrivate
->ProcessorInfo
[ProcessorNumber
], sizeof (EFI_PROCESSOR_INFORMATION
));
71 This service switches the requested AP to be the BSP since the next SMI.
73 @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
74 @param[in] ProcessorNumber The handle number of AP that is to become the new BSP.
76 @retval EFI_SUCCESS BSP will be switched in next SMI.
77 @retval EFI_UNSUPPORTED Switching the BSP or a processor to be hot-removed is not supported.
78 @retval EFI_NOT_FOUND The processor with the handle specified by ProcessorNumber does not exist.
79 @retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
84 IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL
*This
,
85 IN UINTN ProcessorNumber
91 if (ProcessorNumber
>= mMaxNumberOfCpus
) {
92 return EFI_INVALID_PARAMETER
;
95 if (gSmmCpuPrivate
->ProcessorInfo
[ProcessorNumber
].ProcessorId
== INVALID_APIC_ID
) {
99 if (gSmmCpuPrivate
->Operation
[ProcessorNumber
] != SmmCpuNone
||
100 gSmst
->CurrentlyExecutingCpu
== ProcessorNumber
) {
101 return EFI_UNSUPPORTED
;
105 // Setting of the BSP for next SMI is pending until all SMI handlers are finished
107 gSmmCpuPrivate
->Operation
[ProcessorNumber
] = SmmCpuSwitchBsp
;
112 Notify that a processor was hot-added.
114 @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
115 @param[in] ProcessorId Local APIC ID of the hot-added processor.
116 @param[out] ProcessorNumber The handle number of the hot-added processor.
118 @retval EFI_SUCCESS The hot-addition of the specified processors was successfully notified.
119 @retval EFI_UNSUPPORTED Hot addition of processor is not supported.
120 @retval EFI_NOT_FOUND The processor with the handle specified by ProcessorNumber does not exist.
121 @retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
122 @retval EFI_ALREADY_STARTED The processor is already online in the system.
127 IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL
*This
,
128 IN UINT64 ProcessorId
,
129 OUT UINTN
*ProcessorNumber
134 if (!FeaturePcdGet (PcdCpuHotPlugSupport
)) {
135 return EFI_UNSUPPORTED
;
141 if (ProcessorNumber
== NULL
|| ProcessorId
== INVALID_APIC_ID
) {
142 return EFI_INVALID_PARAMETER
;
146 // Check if the processor already exists
149 for (Index
= 0; Index
< mMaxNumberOfCpus
; Index
++) {
150 if (gSmmCpuPrivate
->ProcessorInfo
[Index
].ProcessorId
== ProcessorId
) {
151 return EFI_ALREADY_STARTED
;
156 // Check CPU hot plug data. The CPU RAS handler should have created the mapping
157 // of the APIC ID to SMBASE.
159 for (Index
= 0; Index
< mMaxNumberOfCpus
; Index
++) {
160 if (mCpuHotPlugData
.ApicId
[Index
] == ProcessorId
&&
161 gSmmCpuPrivate
->ProcessorInfo
[Index
].ProcessorId
== INVALID_APIC_ID
) {
162 gSmmCpuPrivate
->ProcessorInfo
[Index
].ProcessorId
= ProcessorId
;
163 gSmmCpuPrivate
->ProcessorInfo
[Index
].StatusFlag
= 0;
164 GetProcessorLocationByApicId (
166 &gSmmCpuPrivate
->ProcessorInfo
[Index
].Location
.Package
,
167 &gSmmCpuPrivate
->ProcessorInfo
[Index
].Location
.Core
,
168 &gSmmCpuPrivate
->ProcessorInfo
[Index
].Location
.Thread
171 *ProcessorNumber
= Index
;
172 gSmmCpuPrivate
->Operation
[Index
] = SmmCpuAdd
;
177 return EFI_INVALID_PARAMETER
;
181 Notify that a processor was hot-removed.
183 @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
184 @param[in] ProcessorNumber The handle number of the hot-added processor.
186 @retval EFI_SUCCESS The hot-removal of the specified processors was successfully notified.
187 @retval EFI_UNSUPPORTED Hot removal of processor is not supported.
188 @retval EFI_UNSUPPORTED Hot removal of BSP is not supported.
189 @retval EFI_UNSUPPORTED Hot removal of a processor with pending hot-plug operation is not supported.
190 @retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
195 IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL
*This
,
196 IN UINTN ProcessorNumber
199 if (!FeaturePcdGet (PcdCpuHotPlugSupport
)) {
200 return EFI_UNSUPPORTED
;
206 if (ProcessorNumber
>= mMaxNumberOfCpus
||
207 gSmmCpuPrivate
->ProcessorInfo
[ProcessorNumber
].ProcessorId
== INVALID_APIC_ID
) {
208 return EFI_INVALID_PARAMETER
;
214 if (ProcessorNumber
== gSmmCpuPrivate
->SmmCoreEntryContext
.CurrentlyExecutingCpu
) {
215 return EFI_UNSUPPORTED
;
218 if (gSmmCpuPrivate
->Operation
[ProcessorNumber
] != SmmCpuNone
) {
219 return EFI_UNSUPPORTED
;
222 gSmmCpuPrivate
->ProcessorInfo
[ProcessorNumber
].ProcessorId
= INVALID_APIC_ID
;
223 mCpuHotPlugData
.ApicId
[ProcessorNumber
] = INVALID_APIC_ID
;
226 // Removal of the processor from the CPU list is pending until all SMI handlers are finished
228 gSmmCpuPrivate
->Operation
[ProcessorNumber
] = SmmCpuRemove
;
233 This return the handle number for the calling processor.
235 @param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
236 @param[out] ProcessorNumber The handle number of currently executing processor.
238 @retval EFI_SUCCESS The current processor handle number was returned
240 @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
246 IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL
*This
,
247 OUT UINTN
*ProcessorNumber
256 if (ProcessorNumber
== NULL
) {
257 return EFI_INVALID_PARAMETER
;
260 ApicId
= GetApicId ();
262 for (Index
= 0; Index
< mMaxNumberOfCpus
; Index
++) {
263 if (gSmmCpuPrivate
->ProcessorInfo
[Index
].ProcessorId
== ApicId
) {
264 *ProcessorNumber
= Index
;
269 // This should not happen
272 return EFI_NOT_FOUND
;
276 Update the SMM CPU list per the pending operation.
278 This function is called after return from SMI handlers.
288 // Handle pending BSP switch operations
290 for (Index
= 0; Index
< mMaxNumberOfCpus
; Index
++) {
291 if (gSmmCpuPrivate
->Operation
[Index
] == SmmCpuSwitchBsp
) {
292 gSmmCpuPrivate
->Operation
[Index
] = SmmCpuNone
;
293 mSmmMpSyncData
->SwitchBsp
= TRUE
;
294 mSmmMpSyncData
->CandidateBsp
[Index
] = TRUE
;
299 // Handle pending hot-add operations
301 for (Index
= 0; Index
< mMaxNumberOfCpus
; Index
++) {
302 if (gSmmCpuPrivate
->Operation
[Index
] == SmmCpuAdd
) {
303 gSmmCpuPrivate
->Operation
[Index
] = SmmCpuNone
;
309 // Handle pending hot-remove operations
311 for (Index
= 0; Index
< mMaxNumberOfCpus
; Index
++) {
312 if (gSmmCpuPrivate
->Operation
[Index
] == SmmCpuRemove
) {
313 gSmmCpuPrivate
->Operation
[Index
] = SmmCpuNone
;
320 Register exception handler.
322 @param This A pointer to the SMM_CPU_SERVICE_PROTOCOL instance.
323 @param ExceptionType Defines which interrupt or exception to hook. Type EFI_EXCEPTION_TYPE and
324 the valid values for this parameter are defined in EFI_DEBUG_SUPPORT_PROTOCOL
325 of the UEFI 2.0 specification.
326 @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER
327 that is called when a processor interrupt occurs.
328 If this parameter is NULL, then the handler will be uninstalled.
330 @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
331 @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was previously installed.
332 @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not previously installed.
333 @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
338 SmmRegisterExceptionHandler (
339 IN EFI_SMM_CPU_SERVICE_PROTOCOL
*This
,
340 IN EFI_EXCEPTION_TYPE ExceptionType
,
341 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
344 return RegisterCpuInterruptHandler (ExceptionType
, InterruptHandler
);
348 Initialize SMM CPU Services.
350 It installs EFI SMM CPU Services Protocol.
352 @param ImageHandle The firmware allocated handle for the EFI image.
354 @retval EFI_SUCCESS EFI SMM CPU Services Protocol was installed successfully.
357 InitializeSmmCpuServices (
363 Status
= gSmst
->SmmInstallProtocolInterface (
365 &gEfiSmmCpuServiceProtocolGuid
,
366 EFI_NATIVE_INTERFACE
,
369 ASSERT_EFI_ERROR (Status
);