public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Ard Biesheuvel" <ard.biesheuvel@linaro.org>
To: Laszlo Ersek <lersek@redhat.com>
Cc: edk2-devel-groups-io <devel@edk2.groups.io>,
	"Igor Mammedov" <imammedo@redhat.com>,
	"Jiewen Yao" <jiewen.yao@intel.com>,
	"Jordan Justen" <jordan.l.justen@intel.com>,
	"Michael Kinney" <michael.d.kinney@intel.com>,
	"Philippe Mathieu-Daudé" <philmd@redhat.com>
Subject: Re: [PATCH v2 12/16] OvmfPkg/CpuHotplugSmm: introduce First SMI Handler for hot-added CPUs
Date: Mon, 2 Mar 2020 15:03:07 +0100	[thread overview]
Message-ID: <CAKv+Gu_eGTGvAHgq=eOA8atV7eAzrST0HD7ri1DjNB7YNvVQHA@mail.gmail.com> (raw)
In-Reply-To: <20200226221156.29589-13-lersek@redhat.com>

On Wed, 26 Feb 2020 at 23:12, Laszlo Ersek <lersek@redhat.com> wrote:
>
> Implement the First SMI Handler for hot-added CPUs, in NASM.
>
> Add the interfacing C-language function that the SMM Monarch calls. This
> function launches and coordinates SMBASE relocation for a hot-added CPU.
>
> 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>

Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

> ---
>
> Notes:
>     v2:
>
>     - implement the combined approach described here:
>
>       http://mid.mail-archive.com/111145fc-be3d-2a9a-a126-c14345a8a8a4@redhat.com
>       https://edk2.groups.io/g/devel/message/54754
>
>       by introducing "FIRST_SMI_HANDLER_CONTEXT.AboutToLeaveSmm".
>
>  OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf        |   4 +
>  OvmfPkg/CpuHotplugSmm/FirstSmiHandlerContext.h |  47 ++++++
>  OvmfPkg/CpuHotplugSmm/Smbase.h                 |  14 ++
>  OvmfPkg/CpuHotplugSmm/FirstSmiHandler.nasm     | 154 +++++++++++++++++++
>  OvmfPkg/CpuHotplugSmm/Smbase.c                 | 157 ++++++++++++++++++++
>  5 files changed, 376 insertions(+)
>
> diff --git a/OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf b/OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf
> index bf4162299c7c..04322b0d7855 100644
> --- a/OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf
> +++ b/OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf
> @@ -5,56 +5,60 @@
>  #
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
>  ##
>
>  [Defines]
>    INF_VERSION                = 1.29
>    PI_SPECIFICATION_VERSION   = 0x00010046                            # PI-1.7.0
>    BASE_NAME                  = CpuHotplugSmm
>    FILE_GUID                  = 84EEA114-C6BE-4445-8F90-51D97863E363
>    MODULE_TYPE                = DXE_SMM_DRIVER
>    ENTRY_POINT                = CpuHotplugEntry
>
>  #
>  # The following information is for reference only and not required by the build
>  # tools.
>  #
>  # VALID_ARCHITECTURES        = IA32 X64
>  #
>
>  [Sources]
>    ApicId.h
>    CpuHotplug.c
> +  FirstSmiHandler.nasm
> +  FirstSmiHandlerContext.h
>    PostSmmPen.nasm
>    QemuCpuhp.c
>    QemuCpuhp.h
>    Smbase.c
>    Smbase.h
>
>  [Packages]
>    MdePkg/MdePkg.dec
>    OvmfPkg/OvmfPkg.dec
>    UefiCpuPkg/UefiCpuPkg.dec
>
>  [LibraryClasses]
>    BaseLib
>    BaseMemoryLib
>    DebugLib
> +  LocalApicLib
>    MmServicesTableLib
>    PcdLib
>    SafeIntLib
> +  SynchronizationLib
>    UefiDriverEntryPoint
>
>  [Protocols]
>    gEfiMmCpuIoProtocolGuid                                           ## CONSUMES
>    gEfiSmmCpuServiceProtocolGuid                                     ## CONSUMES
>
>  [Pcd]
>    gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugDataAddress                ## CONSUMES
>    gUefiOvmfPkgTokenSpaceGuid.PcdQ35SmramAtDefaultSmbase             ## CONSUMES
>
>  [FeaturePcd]
>    gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire                     ## CONSUMES
>
>  [Depex]
>    gEfiMmCpuIoProtocolGuid AND
>    gEfiSmmCpuServiceProtocolGuid
> diff --git a/OvmfPkg/CpuHotplugSmm/FirstSmiHandlerContext.h b/OvmfPkg/CpuHotplugSmm/FirstSmiHandlerContext.h
> new file mode 100644
> index 000000000000..029de4cdea35
> --- /dev/null
> +++ b/OvmfPkg/CpuHotplugSmm/FirstSmiHandlerContext.h
> @@ -0,0 +1,47 @@
> +/** @file
> +  Define the FIRST_SMI_HANDLER_CONTEXT structure, which is an exchange area
> +  between the SMM Monarch and the hot-added CPU, for relocating the SMBASE of
> +  the hot-added CPU.
> +
> +  Copyright (c) 2020, Red Hat, Inc.
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef FIRST_SMI_HANDLER_CONTEXT_H_
> +#define FIRST_SMI_HANDLER_CONTEXT_H_
> +
> +//
> +// The following structure is used to communicate between the SMM Monarch
> +// (running the root MMI handler) and the hot-added CPU (handling its first
> +// SMI). It is placed at SMM_DEFAULT_SMBASE, which is in SMRAM under QEMU's
> +// "SMRAM at default SMBASE" feature.
> +//
> +#pragma pack (1)
> +typedef struct {
> +  //
> +  // When ApicIdGate is MAX_UINT64, then no hot-added CPU may proceed with
> +  // SMBASE relocation.
> +  //
> +  // Otherwise, the hot-added CPU whose APIC ID equals ApicIdGate may proceed
> +  // with SMBASE relocation.
> +  //
> +  // This field is intentionally wider than APIC_ID (UINT32) because we need a
> +  // "gate locked" value that is different from all possible APIC_IDs.
> +  //
> +  UINT64 ApicIdGate;
> +  //
> +  // The new SMBASE value for the hot-added CPU to set in the SMRAM Save State
> +  // Map, before leaving SMM with the RSM instruction.
> +  //
> +  UINT32 NewSmbase;
> +  //
> +  // The hot-added CPU sets this field to 1 right before executing the RSM
> +  // instruction. This tells the SMM Monarch to proceed to polling the last
> +  // byte of the normal RAM reserved page (Post-SMM Pen).
> +  //
> +  UINT8 AboutToLeaveSmm;
> +} FIRST_SMI_HANDLER_CONTEXT;
> +#pragma pack ()
> +
> +#endif // FIRST_SMI_HANDLER_CONTEXT_H_
> diff --git a/OvmfPkg/CpuHotplugSmm/Smbase.h b/OvmfPkg/CpuHotplugSmm/Smbase.h
> index cb5aed98cdd3..e73730d19926 100644
> --- a/OvmfPkg/CpuHotplugSmm/Smbase.h
> +++ b/OvmfPkg/CpuHotplugSmm/Smbase.h
> @@ -1,32 +1,46 @@
>  /** @file
>    SMBASE relocation for hot-plugged CPUs.
>
>    Copyright (c) 2020, Red Hat, Inc.
>
>    SPDX-License-Identifier: BSD-2-Clause-Patent
>  **/
>
>  #ifndef SMBASE_H_
>  #define SMBASE_H_
>
>  #include <Uefi/UefiBaseType.h> // EFI_STATUS
>  #include <Uefi/UefiSpec.h>     // EFI_BOOT_SERVICES
>
> +#include "ApicId.h"            // APIC_ID
> +
>  EFI_STATUS
>  SmbaseAllocatePostSmmPen (
>    OUT UINT32                  *PenAddress,
>    IN  CONST EFI_BOOT_SERVICES *BootServices
>    );
>
>  VOID
>  SmbaseReinstallPostSmmPen (
>    IN UINT32 PenAddress
>    );
>
>  VOID
>  SmbaseReleasePostSmmPen (
>    IN UINT32                  PenAddress,
>    IN CONST EFI_BOOT_SERVICES *BootServices
>    );
>
> +VOID
> +SmbaseInstallFirstSmiHandler (
> +  VOID
> +  );
> +
> +EFI_STATUS
> +SmbaseRelocate (
> +  IN APIC_ID ApicId,
> +  IN UINTN   Smbase,
> +  IN UINT32  PenAddress
> +  );
> +
>  #endif // SMBASE_H_
> diff --git a/OvmfPkg/CpuHotplugSmm/FirstSmiHandler.nasm b/OvmfPkg/CpuHotplugSmm/FirstSmiHandler.nasm
> new file mode 100644
> index 000000000000..5399b5fa4387
> --- /dev/null
> +++ b/OvmfPkg/CpuHotplugSmm/FirstSmiHandler.nasm
> @@ -0,0 +1,154 @@
> +;------------------------------------------------------------------------------
> +; @file
> +; Relocate the SMBASE on a hot-added CPU when it services its first SMI.
> +;
> +; Copyright (c) 2020, Red Hat, Inc.
> +;
> +; SPDX-License-Identifier: BSD-2-Clause-Patent
> +;
> +; The routine runs on the hot-added CPU in the following "big real mode",
> +; 16-bit environment; per "SMI HANDLER EXECUTION ENVIRONMENT" in the Intel SDM
> +; (table "Processor Register Initialization in SMM"):
> +;
> +;  - CS selector: 0x3000 (most significant 16 bits of SMM_DEFAULT_SMBASE).
> +;
> +;  - CS limit: 0xFFFF_FFFF.
> +;
> +;  - CS base: SMM_DEFAULT_SMBASE (0x3_0000).
> +;
> +;  - IP: SMM_HANDLER_OFFSET (0x8000).
> +;
> +;  - ES, SS, DS, FS, GS selectors: 0.
> +;
> +;  - ES, SS, DS, FS, GS limits: 0xFFFF_FFFF.
> +;
> +;  - ES, SS, DS, FS, GS bases: 0.
> +;
> +;  - Operand-size and address-size override prefixes can be used to access the
> +;    address space beyond 1MB.
> +;------------------------------------------------------------------------------
> +
> +SECTION .data
> +BITS 16
> +
> +;
> +; Bring in SMM_DEFAULT_SMBASE from
> +; "MdePkg/Include/Register/Intel/SmramSaveStateMap.h".
> +;
> +SMM_DEFAULT_SMBASE: equ 0x3_0000
> +
> +;
> +; Field offsets in FIRST_SMI_HANDLER_CONTEXT, which resides at
> +; SMM_DEFAULT_SMBASE.
> +;
> +ApicIdGate:      equ  0 ; UINT64
> +NewSmbase:       equ  8 ; UINT32
> +AboutToLeaveSmm: equ 12 ; UINT8
> +
> +;
> +; SMRAM Save State Map field offsets, per the AMD (not Intel) layout that QEMU
> +; implements. Relative to SMM_DEFAULT_SMBASE.
> +;
> +SaveStateRevId:    equ 0xFEFC ; UINT32
> +SaveStateSmbase:   equ 0xFEF8 ; UINT32
> +SaveStateSmbase64: equ 0xFF00 ; UINT32
> +
> +;
> +; CPUID constants, from "MdePkg/Include/Register/Intel/Cpuid.h".
> +;
> +CPUID_SIGNATURE:         equ 0x00
> +CPUID_EXTENDED_TOPOLOGY: equ 0x0B
> +CPUID_VERSION_INFO:      equ 0x01
> +
> +GLOBAL ASM_PFX (mFirstSmiHandler)     ; UINT8[]
> +GLOBAL ASM_PFX (mFirstSmiHandlerSize) ; UINT16
> +
> +ASM_PFX (mFirstSmiHandler):
> +  ;
> +  ; Get our own APIC ID first, so we can contend for ApicIdGate.
> +  ;
> +  ; This basically reimplements GetInitialApicId() from
> +  ; "UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c".
> +  ;
> +  mov eax, CPUID_SIGNATURE
> +  cpuid
> +  cmp eax, CPUID_EXTENDED_TOPOLOGY
> +  jb GetApicIdFromVersionInfo
> +
> +  mov eax, CPUID_EXTENDED_TOPOLOGY
> +  mov ecx, 0
> +  cpuid
> +  test ebx, 0xFFFF
> +  jz GetApicIdFromVersionInfo
> +
> +  ;
> +  ; EDX has the APIC ID, save it to ESI.
> +  ;
> +  mov esi, edx
> +  jmp KnockOnGate
> +
> +GetApicIdFromVersionInfo:
> +  mov eax, CPUID_VERSION_INFO
> +  cpuid
> +  shr ebx, 24
> +  ;
> +  ; EBX has the APIC ID, save it to ESI.
> +  ;
> +  mov esi, ebx
> +
> +KnockOnGate:
> +  ;
> +  ; See if ApicIdGate shows our own APIC ID. If so, swap it to MAX_UINT64
> +  ; (close the gate), and advance. Otherwise, keep knocking.
> +  ;
> +  ; InterlockedCompareExchange64():
> +  ; - Value                   := &FIRST_SMI_HANDLER_CONTEXT.ApicIdGate
> +  ; - CompareValue  (EDX:EAX) := APIC ID (from ESI)
> +  ; - ExchangeValue (ECX:EBX) := MAX_UINT64
> +  ;
> +  mov edx, 0
> +  mov eax, esi
> +  mov ecx, 0xFFFF_FFFF
> +  mov ebx, 0xFFFF_FFFF
> +  lock cmpxchg8b [ds : dword (SMM_DEFAULT_SMBASE + ApicIdGate)]
> +  jz ApicIdMatch
> +  pause
> +  jmp KnockOnGate
> +
> +ApicIdMatch:
> +  ;
> +  ; Update the SMBASE field in the SMRAM Save State Map.
> +  ;
> +  ; First, calculate the address of the SMBASE field, based on the SMM Revision
> +  ; ID; store the result in EBX.
> +  ;
> +  mov eax, dword [ds : dword (SMM_DEFAULT_SMBASE + SaveStateRevId)]
> +  test eax, 0xFFFF
> +  jz LegacySaveStateMap
> +
> +  mov ebx, SMM_DEFAULT_SMBASE + SaveStateSmbase64
> +  jmp UpdateSmbase
> +
> +LegacySaveStateMap:
> +  mov ebx, SMM_DEFAULT_SMBASE + SaveStateSmbase
> +
> +UpdateSmbase:
> +  ;
> +  ; Load the new SMBASE value into EAX.
> +  ;
> +  mov eax, dword [ds : dword (SMM_DEFAULT_SMBASE + NewSmbase)]
> +  ;
> +  ; Save it to the SMBASE field whose address we calculated in EBX.
> +  ;
> +  mov dword [ds : dword ebx], eax
> +  ;
> +  ; Set AboutToLeaveSmm.
> +  ;
> +  mov byte [ds : dword (SMM_DEFAULT_SMBASE + AboutToLeaveSmm)], 1
> +  ;
> +  ; We're done; leave SMM and continue to the pen.
> +  ;
> +  rsm
> +
> +ASM_PFX (mFirstSmiHandlerSize):
> +  dw $ - ASM_PFX (mFirstSmiHandler)
> diff --git a/OvmfPkg/CpuHotplugSmm/Smbase.c b/OvmfPkg/CpuHotplugSmm/Smbase.c
> index ea21153d9145..170571221d84 100644
> --- a/OvmfPkg/CpuHotplugSmm/Smbase.c
> +++ b/OvmfPkg/CpuHotplugSmm/Smbase.c
> @@ -1,38 +1,46 @@
>  /** @file
>    SMBASE relocation for hot-plugged CPUs.
>
>    Copyright (c) 2020, Red Hat, Inc.
>
>    SPDX-License-Identifier: BSD-2-Clause-Patent
>  **/
>
>  #include <Base.h>                             // BASE_1MB
> +#include <Library/BaseLib.h>                  // CpuPause()
>  #include <Library/BaseMemoryLib.h>            // CopyMem()
>  #include <Library/DebugLib.h>                 // DEBUG()
> +#include <Library/LocalApicLib.h>             // SendInitSipiSipi()
> +#include <Library/SynchronizationLib.h>       // InterlockedCompareExchange64()
> +#include <Register/Intel/SmramSaveStateMap.h> // SMM_DEFAULT_SMBASE
> +
> +#include "FirstSmiHandlerContext.h"           // FIRST_SMI_HANDLER_CONTEXT
>
>  #include "Smbase.h"
>
>  extern CONST UINT8 mPostSmmPen[];
>  extern CONST UINT16 mPostSmmPenSize;
> +extern CONST UINT8 mFirstSmiHandler[];
> +extern CONST UINT16 mFirstSmiHandlerSize;
>
>  /**
>    Allocate a non-SMRAM reserved memory page for the Post-SMM Pen for hot-added
>    CPUs.
>
>    This function may only be called from the entry point function of the driver.
>
>    @param[out] PenAddress   The address of the allocated (normal RAM) reserved
>                             page.
>
>    @param[in] BootServices  Pointer to the UEFI boot services table. Used for
>                             allocating the normal RAM (not SMRAM) reserved page.
>
>    @retval EFI_SUCCESS          Allocation successful.
>
>    @retval EFI_BAD_BUFFER_SIZE  The Post-SMM Pen template is not smaller than
>                                 EFI_PAGE_SIZE.
>
>    @return                      Error codes propagated from underlying services.
>                                 DEBUG_ERROR messages have been logged. No
>                                 resources have been allocated.
>  **/
> @@ -89,22 +97,171 @@ SmbaseReinstallPostSmmPen (
>  }
>
>  /**
>    Release the reserved page allocated with SmbaseAllocatePostSmmPen().
>
>    This function may only be called from the entry point function of the driver,
>    on the error path.
>
>    @param[in] PenAddress    The allocation address returned by
>                             SmbaseAllocatePostSmmPen().
>
>    @param[in] BootServices  Pointer to the UEFI boot services table. Used for
>                             releasing the normal RAM (not SMRAM) reserved page.
>  **/
>  VOID
>  SmbaseReleasePostSmmPen (
>    IN UINT32                  PenAddress,
>    IN CONST EFI_BOOT_SERVICES *BootServices
>    )
>  {
>    BootServices->FreePages (PenAddress, 1);
>  }
> +
> +/**
> +  Place the handler routine for the first SMIs of hot-added CPUs at
> +  (SMM_DEFAULT_SMBASE + SMM_HANDLER_OFFSET).
> +
> +  Note that this effects an "SMRAM to SMRAM" copy.
> +
> +  Additionally, shut the APIC ID gate in FIRST_SMI_HANDLER_CONTEXT.
> +
> +  This function may only be called from the entry point function of the driver,
> +  and only after PcdQ35SmramAtDefaultSmbase has been determined to be TRUE.
> +**/
> +VOID
> +SmbaseInstallFirstSmiHandler (
> +  VOID
> +  )
> +{
> +  FIRST_SMI_HANDLER_CONTEXT *Context;
> +
> +  CopyMem ((VOID *)(UINTN)(SMM_DEFAULT_SMBASE + SMM_HANDLER_OFFSET),
> +    mFirstSmiHandler, mFirstSmiHandlerSize);
> +
> +  Context = (VOID *)(UINTN)SMM_DEFAULT_SMBASE;
> +  Context->ApicIdGate = MAX_UINT64;
> +}
> +
> +/**
> +  Relocate the SMBASE on a hot-added CPU. Then pen the hot-added CPU in the
> +  normal RAM reserved memory page, set up earlier with
> +  SmbaseAllocatePostSmmPen() and SmbaseReinstallPostSmmPen().
> +
> +  The SMM Monarch is supposed to call this function from the root MMI handler.
> +
> +  The SMM Monarch is responsible for calling SmbaseInstallFirstSmiHandler(),
> +  SmbaseAllocatePostSmmPen(), and SmbaseReinstallPostSmmPen() before calling
> +  this function.
> +
> +  If the OS maliciously boots the hot-added CPU ahead of letting the ACPI CPU
> +  hotplug event handler broadcast the CPU hotplug MMI, then the hot-added CPU
> +  returns to the OS rather than to the pen, upon RSM. In that case, this
> +  function will hang forever (unless the OS happens to signal back through the
> +  last byte of the pen page).
> +
> +  @param[in] ApicId      The APIC ID of the hot-added CPU whose SMBASE should
> +                         be relocated.
> +
> +  @param[in] Smbase      The new SMBASE address. The root MMI handler is
> +                         responsible for passing in a free ("unoccupied")
> +                         SMBASE address that was pre-configured by
> +                         PiSmmCpuDxeSmm in CPU_HOT_PLUG_DATA.
> +
> +  @param[in] PenAddress  The address of the Post-SMM Pen for hot-added CPUs, as
> +                         returned by SmbaseAllocatePostSmmPen(), and installed
> +                         by SmbaseReinstallPostSmmPen().
> +
> +  @retval EFI_SUCCESS            The SMBASE of the hot-added CPU with APIC ID
> +                                 ApicId has been relocated to Smbase. The
> +                                 hot-added CPU has reported back about leaving
> +                                 SMM.
> +
> +  @retval EFI_PROTOCOL_ERROR     Synchronization bug encountered around
> +                                 FIRST_SMI_HANDLER_CONTEXT.ApicIdGate.
> +
> +  @retval EFI_INVALID_PARAMETER  Smbase does not fit in 32 bits. No relocation
> +                                 has been attempted.
> +**/
> +EFI_STATUS
> +SmbaseRelocate (
> +  IN APIC_ID ApicId,
> +  IN UINTN   Smbase,
> +  IN UINT32  PenAddress
> +  )
> +{
> +  EFI_STATUS                         Status;
> +  volatile UINT8                     *SmmVacated;
> +  volatile FIRST_SMI_HANDLER_CONTEXT *Context;
> +  UINT64                             ExchangeResult;
> +
> +  if (Smbase > MAX_UINT32) {
> +    Status = EFI_INVALID_PARAMETER;
> +    DEBUG ((DEBUG_ERROR, "%a: ApicId=" FMT_APIC_ID " Smbase=0x%Lx: %r\n",
> +      __FUNCTION__, ApicId, (UINT64)Smbase, Status));
> +    return Status;
> +  }
> +
> +  SmmVacated = (UINT8 *)(UINTN)PenAddress + (EFI_PAGE_SIZE - 1);
> +  Context = (VOID *)(UINTN)SMM_DEFAULT_SMBASE;
> +
> +  //
> +  // Clear AboutToLeaveSmm, so we notice when the hot-added CPU is just about
> +  // to reach RSM, and we can proceed to polling the last byte of the reserved
> +  // page (which could be attacked by the OS).
> +  //
> +  Context->AboutToLeaveSmm = 0;
> +
> +  //
> +  // Clear the last byte of the reserved page, so we notice when the hot-added
> +  // CPU checks back in from the pen.
> +  //
> +  *SmmVacated = 0;
> +
> +  //
> +  // Boot the hot-added CPU.
> +  //
> +  // If the OS is benign, and so the hot-added CPU is still in RESET state,
> +  // then the broadcast SMI is still pending for it; it will now launch
> +  // directly into SMM.
> +  //
> +  // If the OS is malicious, the hot-added CPU has been booted already, and so
> +  // it is already spinning on the APIC ID gate. In that case, the
> +  // INIT-SIPI-SIPI below will be ignored.
> +  //
> +  SendInitSipiSipi (ApicId, PenAddress);
> +
> +  //
> +  // Expose the desired new SMBASE value to the hot-added CPU.
> +  //
> +  Context->NewSmbase = (UINT32)Smbase;
> +
> +  //
> +  // Un-gate SMBASE relocation for the hot-added CPU whose APIC ID is ApicId.
> +  //
> +  ExchangeResult = InterlockedCompareExchange64 (&Context->ApicIdGate,
> +                     MAX_UINT64, ApicId);
> +  if (ExchangeResult != MAX_UINT64) {
> +    Status = EFI_PROTOCOL_ERROR;
> +    DEBUG ((DEBUG_ERROR, "%a: ApicId=" FMT_APIC_ID " ApicIdGate=0x%Lx: %r\n",
> +      __FUNCTION__, ApicId, ExchangeResult, Status));
> +    return Status;
> +  }
> +
> +  //
> +  // Wait until the hot-added CPU is just about to execute RSM.
> +  //
> +  while (Context->AboutToLeaveSmm == 0) {
> +    CpuPause ();
> +  }
> +
> +  //
> +  // Now wait until the hot-added CPU reports back from the pen (or the OS
> +  // attacks the last byte of the reserved page).
> +  //
> +  while (*SmmVacated == 0) {
> +    CpuPause ();
> +  }
> +
> +  Status = EFI_SUCCESS;
> +  return Status;
> +}
> --
> 2.19.1.3.g30247aa5d201
>
>

  reply	other threads:[~2020-03-02 14:03 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-26 22:11 [PATCH v2 00/16] OvmfPkg: support VCPU hotplug with -D SMM_REQUIRE Laszlo Ersek
2020-02-26 22:11 ` [PATCH v2 01/16] MdeModulePkg/PiSmmCore: log SMM image start failure Laszlo Ersek
2020-03-02 12:47   ` [edk2-devel] " Laszlo Ersek
2020-03-02 12:55     ` Liming Gao
2020-03-02 13:46   ` Philippe Mathieu-Daudé
2020-03-03  0:46   ` Dong, Eric
2020-02-26 22:11 ` [PATCH v2 02/16] UefiCpuPkg/PiSmmCpuDxeSmm: fix S3 Resume for CPU hotplug Laszlo Ersek
2020-02-28  3:05   ` [edk2-devel] " Dong, Eric
2020-02-28 10:50     ` Laszlo Ersek
2020-03-04 12:23     ` Laszlo Ersek
2020-03-04 14:36       ` Dong, Eric
2020-02-26 22:11 ` [PATCH v2 03/16] OvmfPkg: clone SmmCpuPlatformHookLib from UefiCpuPkg Laszlo Ersek
2020-03-02 13:27   ` Ard Biesheuvel
2020-03-02 13:49   ` Philippe Mathieu-Daudé
2020-02-26 22:11 ` [PATCH v2 04/16] OvmfPkg: enable SMM Monarch Election in PiSmmCpuDxeSmm Laszlo Ersek
2020-03-02 13:32   ` Ard Biesheuvel
2020-02-26 22:11 ` [PATCH v2 05/16] OvmfPkg: enable CPU hotplug support " Laszlo Ersek
2020-03-02 13:33   ` Ard Biesheuvel
2020-02-26 22:11 ` [PATCH v2 06/16] OvmfPkg/CpuHotplugSmm: introduce skeleton for CPU Hotplug SMM driver Laszlo Ersek
2020-03-02 13:44   ` Ard Biesheuvel
2020-02-26 22:11 ` [PATCH v2 07/16] OvmfPkg/CpuHotplugSmm: add hotplug register block helper functions Laszlo Ersek
2020-03-02 13:24   ` Philippe Mathieu-Daudé
2020-03-02 13:45   ` [edk2-devel] " Ard Biesheuvel
2020-02-26 22:11 ` [PATCH v2 08/16] OvmfPkg/CpuHotplugSmm: define the QEMU_CPUHP_CMD_GET_ARCH_ID macro Laszlo Ersek
2020-03-02 13:22   ` Philippe Mathieu-Daudé
2020-03-02 13:45   ` Ard Biesheuvel
2020-02-26 22:11 ` [PATCH v2 09/16] OvmfPkg/CpuHotplugSmm: add function for collecting CPUs with events Laszlo Ersek
2020-03-02 13:49   ` Ard Biesheuvel
2020-03-02 20:34   ` Philippe Mathieu-Daudé
2020-03-03 10:31     ` Laszlo Ersek
2020-02-26 22:11 ` [PATCH v2 10/16] OvmfPkg/CpuHotplugSmm: collect " Laszlo Ersek
2020-03-02 13:58   ` Ard Biesheuvel
2020-02-26 22:11 ` [PATCH v2 11/16] OvmfPkg/CpuHotplugSmm: introduce Post-SMM Pen for hot-added CPUs Laszlo Ersek
2020-03-02 14:02   ` [edk2-devel] " Ard Biesheuvel
2020-02-26 22:11 ` [PATCH v2 12/16] OvmfPkg/CpuHotplugSmm: introduce First SMI Handler " Laszlo Ersek
2020-03-02 14:03   ` Ard Biesheuvel [this message]
2020-02-26 22:11 ` [PATCH v2 13/16] OvmfPkg/CpuHotplugSmm: complete root MMI handler for CPU hotplug Laszlo Ersek
2020-03-02 14:05   ` Ard Biesheuvel
2020-02-26 22:11 ` [PATCH v2 14/16] OvmfPkg: clone CpuS3DataDxe from UefiCpuPkg Laszlo Ersek
2020-03-02 13:44   ` Philippe Mathieu-Daudé
2020-03-02 14:06   ` Ard Biesheuvel
2020-02-26 22:11 ` [PATCH v2 15/16] OvmfPkg/CpuS3DataDxe: superficial cleanups Laszlo Ersek
2020-03-02 13:25   ` Philippe Mathieu-Daudé
2020-03-02 14:06   ` Ard Biesheuvel
2020-02-26 22:11 ` [PATCH v2 16/16] OvmfPkg/CpuS3DataDxe: enable S3 resume after CPU hotplug Laszlo Ersek
2020-03-02 14:16   ` Ard Biesheuvel
2020-03-02 15:46 ` [edk2-devel] [PATCH v2 00/16] OvmfPkg: support VCPU hotplug with -D SMM_REQUIRE Boris Ostrovsky
2020-03-02 19:22   ` Laszlo Ersek
2020-03-02 19:59 ` Laszlo Ersek
2020-03-04 13:29   ` Philippe Mathieu-Daudé
2020-03-04 18:09     ` Laszlo Ersek
2020-03-04 12:29 ` Laszlo Ersek
2020-03-05  8:32   ` Laszlo Ersek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAKv+Gu_eGTGvAHgq=eOA8atV7eAzrST0HD7ri1DjNB7YNvVQHA@mail.gmail.com' \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox