2 Root SMI handler for VCPU hotplug SMIs.
4 Copyright (c) 2020, Red Hat, Inc.
6 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include <IndustryStandard/Q35MchIch9.h> // ICH9_APM_CNT
10 #include <Library/BaseLib.h> // CpuDeadLoop()
11 #include <Library/DebugLib.h> // ASSERT()
12 #include <Library/MmServicesTableLib.h> // gMmst
13 #include <Library/PcdLib.h> // PcdGetBool()
14 #include <Protocol/MmCpuIo.h> // EFI_MM_CPU_IO_PROTOCOL
15 #include <Uefi/UefiBaseType.h> // EFI_STATUS
18 // We use this protocol for accessing IO Ports.
20 STATIC EFI_MM_CPU_IO_PROTOCOL
*mMmCpuIo
;
22 // Represents the registration of the CPU Hotplug MMI handler.
24 STATIC EFI_HANDLE mDispatchHandle
;
28 CPU Hotplug MMI handler function.
30 This is a root MMI handler.
32 @param[in] DispatchHandle The unique handle assigned to this handler by
33 EFI_MM_SYSTEM_TABLE.MmiHandlerRegister().
35 @param[in] Context Context passed in by
36 EFI_MM_SYSTEM_TABLE.MmiManage(). Due to
37 CpuHotplugMmi() being a root MMI handler,
38 Context is ASSERT()ed to be NULL.
40 @param[in,out] CommBuffer Ignored, due to CpuHotplugMmi() being a root
43 @param[in,out] CommBufferSize Ignored, due to CpuHotplugMmi() being a root
46 @retval EFI_SUCCESS The MMI was handled and the MMI
47 source was quiesced. When returned
48 by a non-root MMI handler,
49 EFI_SUCCESS terminates the
50 processing of MMI handlers in
51 EFI_MM_SYSTEM_TABLE.MmiManage().
52 For a root MMI handler (i.e., for
53 the present function too),
54 EFI_SUCCESS behaves identically to
55 EFI_WARN_INTERRUPT_SOURCE_QUIESCED,
56 as further root MMI handlers are
58 EFI_MM_SYSTEM_TABLE.MmiManage()
61 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The MMI source has been quiesced,
62 but other handlers should still
65 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The MMI source is still pending,
66 and other handlers should still
69 @retval EFI_INTERRUPT_PENDING The MMI source could not be
76 IN EFI_HANDLE DispatchHandle
,
77 IN CONST VOID
*Context OPTIONAL
,
78 IN OUT VOID
*CommBuffer OPTIONAL
,
79 IN OUT UINTN
*CommBufferSize OPTIONAL
86 // Assert that we are entering this function due to our root MMI handler
89 ASSERT (DispatchHandle
== mDispatchHandle
);
91 // When MmiManage() is invoked to process root MMI handlers, the caller (the
92 // MM Core) is expected to pass in a NULL Context. MmiManage() then passes
93 // the same NULL Context to individual handlers.
95 ASSERT (Context
== NULL
);
97 // Read the MMI command value from the APM Control Port, to see if this is an
98 // MMI we should care about.
100 Status
= mMmCpuIo
->Io
.Read (mMmCpuIo
, MM_IO_UINT8
, ICH9_APM_CNT
, 1,
102 if (EFI_ERROR (Status
)) {
103 DEBUG ((DEBUG_ERROR
, "%a: failed to read ICH9_APM_CNT: %r\n", __FUNCTION__
,
106 // We couldn't even determine if the MMI was for us or not.
111 if (ApmControl
!= ICH9_APM_CNT_CPU_HOTPLUG
) {
113 // The MMI is not for us.
115 return EFI_WARN_INTERRUPT_SOURCE_QUIESCED
;
119 // We've handled this MMI.
127 // We couldn't handle this MMI.
129 return EFI_INTERRUPT_PENDING
;
134 // Entry point function of this driver.
139 IN EFI_HANDLE ImageHandle
,
140 IN EFI_SYSTEM_TABLE
*SystemTable
146 // This module should only be included when SMM support is required.
148 ASSERT (FeaturePcdGet (PcdSmmSmramRequire
));
150 // This driver depends on the dynamically detected "SMRAM at default SMBASE"
153 if (!PcdGetBool (PcdQ35SmramAtDefaultSmbase
)) {
154 return EFI_UNSUPPORTED
;
158 // Errors from here on are fatal; we cannot allow the boot to proceed if we
159 // can't set up this driver to handle CPU hotplug.
161 // First, collect the protocols needed later. All of these protocols are
162 // listed in our module DEPEX.
164 Status
= gMmst
->MmLocateProtocol (&gEfiMmCpuIoProtocolGuid
,
165 NULL
/* Registration */, (VOID
**)&mMmCpuIo
);
166 if (EFI_ERROR (Status
)) {
167 DEBUG ((DEBUG_ERROR
, "%a: locate MmCpuIo: %r\n", __FUNCTION__
, Status
));
172 // Register the handler for the CPU Hotplug MMI.
174 Status
= gMmst
->MmiHandlerRegister (
176 NULL
, // HandlerType: root MMI handler
179 if (EFI_ERROR (Status
)) {
180 DEBUG ((DEBUG_ERROR
, "%a: MmiHandlerRegister(): %r\n", __FUNCTION__
,