]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/CpuHotplugSmm: introduce skeleton for CPU Hotplug SMM driver
authorLaszlo Ersek <lersek@redhat.com>
Wed, 26 Feb 2020 22:11:46 +0000 (23:11 +0100)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Wed, 4 Mar 2020 12:22:07 +0000 (12:22 +0000)
Add a new SMM driver skeleton that registers a root SMI handler, and
checks if the SMI control value (written to 0xB2) indicates a CPU hotplug
SMI.

QEMU's ACPI payload will cause the OS to raise a broadcast SMI when a CPU
hotplug event occurs, namely by writing value 4 to IO Port 0xB2. In other
words, control value 4 is now allocated for this purpose; introduce the
ICH9_APM_CNT_CPU_HOTPLUG macro for it.

The standard identifiers in this driver use the new MM (Management Mode)
terminology from the PI spec, not the earlier SMM (System Management Mode)
terms.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Michael Kinney <michael.d.kinney@intel.com>
Cc: Philippe Mathieu-Daudé <philmd@redhat.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1512
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20200226221156.29589-7-lersek@redhat.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
OvmfPkg/CpuHotplugSmm/CpuHotplug.c [new file with mode: 0644]
OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf [new file with mode: 0644]
OvmfPkg/Include/IndustryStandard/Q35MchIch9.h
OvmfPkg/OvmfPkgIa32.dsc
OvmfPkg/OvmfPkgIa32.fdf
OvmfPkg/OvmfPkgIa32X64.dsc
OvmfPkg/OvmfPkgIa32X64.fdf
OvmfPkg/OvmfPkgX64.dsc
OvmfPkg/OvmfPkgX64.fdf

diff --git a/OvmfPkg/CpuHotplugSmm/CpuHotplug.c b/OvmfPkg/CpuHotplugSmm/CpuHotplug.c
new file mode 100644 (file)
index 0000000..fd09403
--- /dev/null
@@ -0,0 +1,191 @@
+/** @file\r
+  Root SMI handler for VCPU hotplug SMIs.\r
+\r
+  Copyright (c) 2020, Red Hat, Inc.\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+**/\r
+\r
+#include <IndustryStandard/Q35MchIch9.h>     // ICH9_APM_CNT\r
+#include <Library/BaseLib.h>                 // CpuDeadLoop()\r
+#include <Library/DebugLib.h>                // ASSERT()\r
+#include <Library/MmServicesTableLib.h>      // gMmst\r
+#include <Library/PcdLib.h>                  // PcdGetBool()\r
+#include <Protocol/MmCpuIo.h>                // EFI_MM_CPU_IO_PROTOCOL\r
+#include <Uefi/UefiBaseType.h>               // EFI_STATUS\r
+\r
+//\r
+// We use this protocol for accessing IO Ports.\r
+//\r
+STATIC EFI_MM_CPU_IO_PROTOCOL *mMmCpuIo;\r
+//\r
+// Represents the registration of the CPU Hotplug MMI handler.\r
+//\r
+STATIC EFI_HANDLE mDispatchHandle;\r
+\r
+\r
+/**\r
+  CPU Hotplug MMI handler function.\r
+\r
+  This is a root MMI handler.\r
+\r
+  @param[in] DispatchHandle      The unique handle assigned to this handler by\r
+                                 EFI_MM_SYSTEM_TABLE.MmiHandlerRegister().\r
+\r
+  @param[in] Context             Context passed in by\r
+                                 EFI_MM_SYSTEM_TABLE.MmiManage(). Due to\r
+                                 CpuHotplugMmi() being a root MMI handler,\r
+                                 Context is ASSERT()ed to be NULL.\r
+\r
+  @param[in,out] CommBuffer      Ignored, due to CpuHotplugMmi() being a root\r
+                                 MMI handler.\r
+\r
+  @param[in,out] CommBufferSize  Ignored, due to CpuHotplugMmi() being a root\r
+                                 MMI handler.\r
+\r
+  @retval EFI_SUCCESS                       The MMI was handled and the MMI\r
+                                            source was quiesced. When returned\r
+                                            by a non-root MMI handler,\r
+                                            EFI_SUCCESS terminates the\r
+                                            processing of MMI handlers in\r
+                                            EFI_MM_SYSTEM_TABLE.MmiManage().\r
+                                            For a root MMI handler (i.e., for\r
+                                            the present function too),\r
+                                            EFI_SUCCESS behaves identically to\r
+                                            EFI_WARN_INTERRUPT_SOURCE_QUIESCED,\r
+                                            as further root MMI handlers are\r
+                                            going to be called by\r
+                                            EFI_MM_SYSTEM_TABLE.MmiManage()\r
+                                            anyway.\r
+\r
+  @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED  The MMI source has been quiesced,\r
+                                              but other handlers should still\r
+                                              be called.\r
+\r
+  @retval EFI_WARN_INTERRUPT_SOURCE_PENDING   The MMI source is still pending,\r
+                                              and other handlers should still\r
+                                              be called.\r
+\r
+  @retval EFI_INTERRUPT_PENDING               The MMI source could not be\r
+                                              quiesced.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+CpuHotplugMmi (\r
+  IN EFI_HANDLE DispatchHandle,\r
+  IN CONST VOID *Context        OPTIONAL,\r
+  IN OUT VOID   *CommBuffer     OPTIONAL,\r
+  IN OUT UINTN  *CommBufferSize OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+  UINT8      ApmControl;\r
+\r
+  //\r
+  // Assert that we are entering this function due to our root MMI handler\r
+  // registration.\r
+  //\r
+  ASSERT (DispatchHandle == mDispatchHandle);\r
+  //\r
+  // When MmiManage() is invoked to process root MMI handlers, the caller (the\r
+  // MM Core) is expected to pass in a NULL Context. MmiManage() then passes\r
+  // the same NULL Context to individual handlers.\r
+  //\r
+  ASSERT (Context == NULL);\r
+  //\r
+  // Read the MMI command value from the APM Control Port, to see if this is an\r
+  // MMI we should care about.\r
+  //\r
+  Status = mMmCpuIo->Io.Read (mMmCpuIo, MM_IO_UINT8, ICH9_APM_CNT, 1,\r
+                          &ApmControl);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: failed to read ICH9_APM_CNT: %r\n", __FUNCTION__,\r
+      Status));\r
+    //\r
+    // We couldn't even determine if the MMI was for us or not.\r
+    //\r
+    goto Fatal;\r
+  }\r
+\r
+  if (ApmControl != ICH9_APM_CNT_CPU_HOTPLUG) {\r
+    //\r
+    // The MMI is not for us.\r
+    //\r
+    return EFI_WARN_INTERRUPT_SOURCE_QUIESCED;\r
+  }\r
+\r
+  //\r
+  // We've handled this MMI.\r
+  //\r
+  return EFI_SUCCESS;\r
+\r
+Fatal:\r
+  ASSERT (FALSE);\r
+  CpuDeadLoop ();\r
+  //\r
+  // We couldn't handle this MMI.\r
+  //\r
+  return EFI_INTERRUPT_PENDING;\r
+}\r
+\r
+\r
+//\r
+// Entry point function of this driver.\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+CpuHotplugEntry (\r
+  IN EFI_HANDLE       ImageHandle,\r
+  IN EFI_SYSTEM_TABLE *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  // This module should only be included when SMM support is required.\r
+  //\r
+  ASSERT (FeaturePcdGet (PcdSmmSmramRequire));\r
+  //\r
+  // This driver depends on the dynamically detected "SMRAM at default SMBASE"\r
+  // feature.\r
+  //\r
+  if (!PcdGetBool (PcdQ35SmramAtDefaultSmbase)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Errors from here on are fatal; we cannot allow the boot to proceed if we\r
+  // can't set up this driver to handle CPU hotplug.\r
+  //\r
+  // First, collect the protocols needed later. All of these protocols are\r
+  // listed in our module DEPEX.\r
+  //\r
+  Status = gMmst->MmLocateProtocol (&gEfiMmCpuIoProtocolGuid,\r
+                    NULL /* Registration */, (VOID **)&mMmCpuIo);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: locate MmCpuIo: %r\n", __FUNCTION__, Status));\r
+    goto Fatal;\r
+  }\r
+\r
+  //\r
+  // Register the handler for the CPU Hotplug MMI.\r
+  //\r
+  Status = gMmst->MmiHandlerRegister (\r
+                    CpuHotplugMmi,\r
+                    NULL,            // HandlerType: root MMI handler\r
+                    &mDispatchHandle\r
+                    );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: MmiHandlerRegister(): %r\n", __FUNCTION__,\r
+      Status));\r
+    goto Fatal;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+Fatal:\r
+  ASSERT (FALSE);\r
+  CpuDeadLoop ();\r
+  return Status;\r
+}\r
diff --git a/OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf b/OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf
new file mode 100644 (file)
index 0000000..fa70858
--- /dev/null
@@ -0,0 +1,48 @@
+## @file\r
+# Root SMI handler for VCPU hotplug SMIs.\r
+#\r
+# Copyright (c) 2020, Red Hat, Inc.\r
+#\r
+# SPDX-License-Identifier: BSD-2-Clause-Patent\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                = 1.29\r
+  PI_SPECIFICATION_VERSION   = 0x00010046                            # PI-1.7.0\r
+  BASE_NAME                  = CpuHotplugSmm\r
+  FILE_GUID                  = 84EEA114-C6BE-4445-8F90-51D97863E363\r
+  MODULE_TYPE                = DXE_SMM_DRIVER\r
+  ENTRY_POINT                = CpuHotplugEntry\r
+\r
+#\r
+# The following information is for reference only and not required by the build\r
+# tools.\r
+#\r
+# VALID_ARCHITECTURES        = IA32 X64\r
+#\r
+\r
+[Sources]\r
+  CpuHotplug.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  OvmfPkg/OvmfPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  DebugLib\r
+  MmServicesTableLib\r
+  PcdLib\r
+  UefiDriverEntryPoint\r
+\r
+[Protocols]\r
+  gEfiMmCpuIoProtocolGuid                                           ## CONSUMES\r
+\r
+[Pcd]\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdQ35SmramAtDefaultSmbase             ## CONSUMES\r
+\r
+[FeaturePcd]\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire                     ## CONSUMES\r
+\r
+[Depex]\r
+  gEfiMmCpuIoProtocolGuid\r
index cb705fee92ca91770bb8d953cea538effb7f830a..73db4b59a1112840b0fdf9d3210412fe869d19db 100644 (file)
 //\r
 // IO ports\r
 //\r
-#define ICH9_APM_CNT 0xB2\r
-#define ICH9_APM_STS 0xB3\r
+#define ICH9_APM_CNT              0xB2\r
+#define ICH9_APM_CNT_CPU_HOTPLUG    0x04\r
+#define ICH9_APM_STS              0xB3\r
 \r
 #define ICH9_CPU_HOTPLUG_BASE 0x0CD8\r
 \r
index 25e704be10ee529b9b28973f2e9f9f83a985acae..7a8a49af9584c66b2e396168191be18d60d2a082 100644 (file)
   #\r
   # Privileged drivers (DXE_SMM_DRIVER modules)\r
   #\r
+  OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf\r
   UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf\r
   MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf {\r
     <LibraryClasses>\r
index 2e12807282becf204e98c2d4de87c1d63f0eec80..d58214eb80ff50e5e74734573f5818441fdd68f1 100644 (file)
@@ -322,6 +322,7 @@ INF  OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.inf
 INF  UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf\r
 INF  MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf\r
 INF  MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf\r
+INF  OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf\r
 INF  UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf\r
 INF  MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf\r
 INF  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf\r
index 6def3f0c20c66fd53d94d92954ee81104b138ade..67c1635e33163f2bfb99e2ec39e40637ac2756a6 100644 (file)
   #\r
   # Privileged drivers (DXE_SMM_DRIVER modules)\r
   #\r
+  OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf\r
   UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf\r
   MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf {\r
     <LibraryClasses>\r
index d67d3368764272438b066c650f2d8f1ce17e35cb..c21c3b92d8e544f29e39aaae3e630c67ea912895 100644 (file)
@@ -329,6 +329,7 @@ INF  OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.inf
 INF  UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf\r
 INF  MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf\r
 INF  MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf\r
+INF  OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf\r
 INF  UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf\r
 INF  MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf\r
 INF  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf\r
index 2c1902f9f22ae0b146c186905b6c35a2c9696e5c..45014190a6cbe18fcc4bcd8542a3fc0f1a75800b 100644 (file)
   #\r
   # Privileged drivers (DXE_SMM_DRIVER modules)\r
   #\r
+  OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf\r
   UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf\r
   MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf {\r
     <LibraryClasses>\r
index d67d3368764272438b066c650f2d8f1ce17e35cb..c21c3b92d8e544f29e39aaae3e630c67ea912895 100644 (file)
@@ -329,6 +329,7 @@ INF  OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.inf
 INF  UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf\r
 INF  MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf\r
 INF  MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf\r
+INF  OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf\r
 INF  UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf\r
 INF  MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf\r
 INF  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf\r