public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Jordan Justen <jordan.l.justen@intel.com>
To: Laszlo Ersek <lersek@redhat.com>,
	"edk2-devel-01" <edk2-devel@lists.01.org>
Cc: "Michael Kinney" <michael.d.kinney@intel.com>,
	"Jeff Fan" <jeff.fan@intel.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>
Subject: Re: [PATCH v2 4/4] OvmfPkg/SmmControl2Dxe: select broadcast SMI if available
Date: Tue, 22 Nov 2016 19:44:05 -0800	[thread overview]
Message-ID: <147987264544.21600.17139942187851594260@jljusten-ivb> (raw)
In-Reply-To: <20161118135249.26018-5-lersek@redhat.com>

On 2016-11-18 05:52:49, Laszlo Ersek wrote:
> When writing to IO port 0xB2 (ICH9_APM_CNT), QEMU by default injects an
> SMI only on the VCPU that is writing the port. This has exposed corner
> cases and strange behavior with edk2 code, which generally expects a
> software SMI to affect all CPUs at once. We've experienced instability
> despite the fact that OVMF sets PcdCpuSmmApSyncTimeout and
> PcdCpuSmmSyncMode differently from the UefiCpuPkg defaults, such that they
> match QEMU's unicast SMIs better. (Refer to edk2 commits 9b1e378811ff and
> bb0f18b0bce6.)
> 
> Using the feature negotiation specified in QEMU's
> "docs/specs/q35-apm-sts.txt", we can ask QEMU to broadcast SMIs.
> Extensive testing from earlier proves that broadcast SMIs are only
> reliable if we use the UefiCpuPkg defaults for the above PCDs. With those
> settings however, the broadcast is very reliable -- the most reliable
> configuration encountered thus far.
> 
> Therefore negotiate broadcast SMIs with QEMU, and if the negotiation is
> successful, dynamically revert the PCDs to the UefiCpuPkg defaults.
> 
> Setting the PCDs in this module is safe:
> 
> - only PiSmmCpuDxeSmm consumes them,
> 
> - PiSmmCpuDxeSmm is a DXE_SMM_DRIVER, launched by the SMM_CORE
>   (MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf),
> 
> - the SMM_CORE is launched by the SMM IPL runtime DXE driver
>   (MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf),
> 
> - the SMM IPL has a DEPEX on EFI_SMM_CONTROL2_PROTOCOL,
> 
> - OvmfPkg/SmmControl2Dxe produces that protocol.
> 
> The end result is that PiSmmCpuDxeSmm cannot be dispatched before
> SmmControl2Dxe installs EFI_SMM_CONTROL2_PROTOCOL and returns from its
> entry point. Hence we can set the PCD's consumed by PiSmmCpuDxeSmm in
> SmmControl2Dxe.
> 
> Cc: Jeff Fan <jeff.fan@intel.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Michael Kinney <michael.d.kinney@intel.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=230
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Laszlo Ersek <lersek@redhat.com>
> ---
> 
> Notes:
>     v2:
>     - negotiate the broadcast SMI feature
>     - make the S3 boot script re-select it if it's available at first boot
>     - set PiSmmCpuDxeSmm's PCD's dynamically
> 
>  OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.inf |  5 ++
>  OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.c   | 73 +++++++++++++++++++-
>  2 files changed, 75 insertions(+), 3 deletions(-)
> 
> diff --git a/OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.inf b/OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.inf
> index 0e9f98c2871c..c28832435eed 100644
> --- a/OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.inf
> +++ b/OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.inf
> @@ -44,6 +44,7 @@ [Sources]
>  [Packages]
>    MdePkg/MdePkg.dec
>    OvmfPkg/OvmfPkg.dec
> +  UefiCpuPkg/UefiCpuPkg.dec
>  
>  [LibraryClasses]
>    BaseLib
> @@ -59,6 +60,10 @@ [Protocols]
>    gEfiS3SaveStateProtocolGuid   ## SOMETIMES_CONSUMES
>    gEfiSmmControl2ProtocolGuid   ## PRODUCES
>  
> +[Pcd]
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmApSyncTimeout ## SOMETIMES_PRODUCES
> +  gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmSyncMode      ## SOMETIMES_PRODUCES
> +
>  [FeaturePcd]
>    gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
>  
> diff --git a/OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.c b/OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.c
> index 82549b0a7e35..6f05797979de 100644
> --- a/OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.c
> +++ b/OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.c
> @@ -56,6 +56,15 @@ OnS3SaveStateInstalled (
>  STATIC UINTN mSmiEnable;
>  //
> +// The indicator whether we have negotiated with QEMU to broadcast the SMI to
> +// all VCPUs whenever we write to ICH9_APM_CNT in our
> +// EFI_SMM_CONTROL2_PROTOCOL.Trigger() implementation. This variable is only
> +// used to carry information from the entry point function to the S3SaveState
> +// protocol installation callback.
> +//
> +STATIC BOOLEAN mSmiBroadcast;

I think you are relying on uninitialized static data being zero'd.

Does it hurt to actually set it to FALSE?

I'm glad we'll be using a mechanism that broadcasts to all the
processors like the real hardware. It is a bit unfortunate that it
doesn't go through the b2 port for it.

Did you get a chance to test variable writes on Windows with this
change? I know Windows can be more picky about port accesses...

Series Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>

Thanks!

> +
> +//
>  // Event signaled when an S3SaveState protocol interface is installed.
>  //
>  STATIC EFI_EVENT mS3SaveStateInstalled;
> @@ -107,10 +116,10 @@ SmmControl2DxeTrigger (
>    // report about hardware status, while this register is fully governed by
>    // software.
>    //
> -  // Write to the status register first, as this won't trigger the SMI just
> -  // yet. Then write to the control register.
> +  // QEMU utilizes the status register for feature negotiation, therefore we
> +  // can't accept external data.
>    //
> -  IoWrite8 (ICH9_APM_STS, DataPort    == NULL ? 0 : *DataPort);
> +  ASSERT (DataPort == NULL);
>    IoWrite8 (ICH9_APM_CNT, CommandPort == NULL ? 0 : *CommandPort);
>    return EFI_SUCCESS;
>  }
> @@ -177,6 +186,7 @@ SmmControl2DxeEntryPoint (
>  {
>    UINT32     PmBase;
>    UINT32     SmiEnableVal;
> +  UINT8      ApmStatusVal;
>    EFI_STATUS Status;
>  
>    //
> @@ -229,6 +239,43 @@ SmmControl2DxeEntryPoint (
>      goto FatalError;
>    }
>  
> +  //
> +  // Negotiate broadcast SMI with QEMU.
> +  //
> +  IoWrite8 (ICH9_APM_STS, QEMU_ICH9_APM_STS_GET_SET_FEAT);
> +  ApmStatusVal = IoRead8 (ICH9_APM_STS);
> +  if ((ApmStatusVal & QEMU_ICH9_APM_STS_GET_SET_FEAT) != 0) {
> +    DEBUG ((DEBUG_VERBOSE, "%a: SMI feature negotiation unavailable\n",
> +      __FUNCTION__));
> +    IoWrite8 (ICH9_APM_STS, 0);
> +  } else if ((ApmStatusVal & QEMU_ICH9_APM_STS_F_BCAST_SMI) == 0) {
> +    DEBUG ((DEBUG_VERBOSE, "%a: SMI broadcast unavailable\n", __FUNCTION__));
> +  } else {
> +    //
> +    // Request the broadcast feature, and nothing else. Check for confirmation.
> +    //
> +    IoWrite8 (ICH9_APM_STS, QEMU_ICH9_APM_STS_F_BCAST_SMI);
> +    ApmStatusVal = IoRead8 (ICH9_APM_STS);
> +    if ((ApmStatusVal & QEMU_ICH9_APM_STS_GET_SET_FEAT) != 0) {
> +      DEBUG ((DEBUG_VERBOSE, "%a: failed to negotiate SMI broadcast\n",
> +        __FUNCTION__));
> +    } else {
> +      //
> +      // Configure the traditional AP sync / SMI delivery mode for
> +      // PiSmmCpuDxeSmm. Effectively, restore the UefiCpuPkg defaults, from
> +      // which the original QEMU behavior (i.e., unicast SMI) used to differ.
> +      //
> +      if (RETURN_ERROR (PcdSet64S (PcdCpuSmmApSyncTimeout, 1000000)) ||
> +          RETURN_ERROR (PcdSet8S (PcdCpuSmmSyncMode, 0x00))) {
> +        DEBUG ((DEBUG_ERROR, "%a: PiSmmCpuDxeSmm PCD configuration failed\n",
> +          __FUNCTION__));
> +        goto FatalError;
> +      }
> +      mSmiBroadcast = TRUE;
> +      DEBUG ((DEBUG_INFO, "%a: using SMI broadcast\n", __FUNCTION__));
> +    }
> +  }
> +
>    if (QemuFwCfgS3Enabled ()) {
>      VOID *Registration;
>  
> @@ -360,6 +407,26 @@ OnS3SaveStateInstalled (
>      CpuDeadLoop ();
>    }
>  
> +  if (mSmiBroadcast) {
> +    UINT8 ApmStatusVal;
> +
> +    ApmStatusVal = QEMU_ICH9_APM_STS_F_BCAST_SMI;
> +    Status = S3SaveState->Write (
> +                            S3SaveState,
> +                            EFI_BOOT_SCRIPT_IO_WRITE_OPCODE,
> +                            EfiBootScriptWidthUint8,
> +                            (UINT64)ICH9_APM_STS,
> +                            (UINTN)1,
> +                            &ApmStatusVal
> +                            );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((DEBUG_ERROR, "%a: EFI_BOOT_SCRIPT_IO_WRITE_OPCODE: %r\n",
> +        __FUNCTION__, Status));
> +      ASSERT (FALSE);
> +      CpuDeadLoop ();
> +    }
> +  }
> +
>    DEBUG ((EFI_D_VERBOSE, "%a: boot script fragment saved\n", __FUNCTION__));
>    gBS->CloseEvent (Event);
>    mS3SaveStateInstalled = NULL;
> -- 
> 2.9.2
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


  reply	other threads:[~2016-11-23  3:44 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-18 13:52 [PATCH v2 0/4] OvmfPkg: broadcast SMIs and dynamically revert to traditional AP sync mode Laszlo Ersek
2016-11-18 13:52 ` [PATCH v2 1/4] UefiCpuPkg/PiSmmCpuDxeSmm: dynamic PcdCpuSmmApSyncTimeout, PcdCpuSmmSyncMode Laszlo Ersek
2016-11-22  7:20   ` Fan, Jeff
2016-11-22  8:06     ` Laszlo Ersek
2016-11-22  8:09       ` Laszlo Ersek
2016-11-18 13:52 ` [PATCH v2 2/4] OvmfPkg: dynamic defaults for " Laszlo Ersek
2016-11-18 13:52 ` [PATCH v2 3/4] OvmfPkg/IndustryStandard: add macros for QEMU's SMI feature control bits Laszlo Ersek
2016-11-18 13:52 ` [PATCH v2 4/4] OvmfPkg/SmmControl2Dxe: select broadcast SMI if available Laszlo Ersek
2016-11-23  3:44   ` Jordan Justen [this message]
2016-11-23 15:44     ` Laszlo Ersek
2016-12-01 20:30       ` 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=147987264544.21600.17139942187851594260@jljusten-ivb \
    --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