From: "Michael D Kinney" <michael.d.kinney@intel.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>,
"lersek@redhat.com" <lersek@redhat.com>,
"Kinney, Michael D" <michael.d.kinney@intel.com>
Cc: "Dong, Eric" <eric.dong@intel.com>, "Ni, Ray" <ray.ni@intel.com>,
"Wang, Jian J" <jian.j.wang@intel.com>
Subject: Re: [edk2-devel] [Patch 2/4] UefiCpuPkg/MpInitLib: Avoid MSR_IA32_APIC_BASE for single core
Date: Tue, 30 Apr 2019 15:21:38 +0000 [thread overview]
Message-ID: <E92EE9817A31E24EB0585FDF735412F5B9CA031C@ORSMSX113.amr.corp.intel.com> (raw)
In-Reply-To: <e77dc9a9-6506-a33c-dfd5-121d5867a31b@redhat.com>
Laszlo,
I agree with your analysis. I will work on a
different solution.
Thanks,
Mike
> -----Original Message-----
> From: devel@edk2.groups.io
> [mailto:devel@edk2.groups.io] On Behalf Of Laszlo Ersek
> Sent: Tuesday, April 30, 2019 3:02 AM
> To: Kinney, Michael D <michael.d.kinney@intel.com>;
> devel@edk2.groups.io
> Cc: Dong, Eric <eric.dong@intel.com>; Ni, Ray
> <ray.ni@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>
> Subject: Re: [edk2-devel] [Patch 2/4]
> UefiCpuPkg/MpInitLib: Avoid MSR_IA32_APIC_BASE for
> single core
>
> On 04/29/19 19:11, Kinney, Michael D wrote:
> > Laszlo,
> >
> > I was attempting to follow the equivalent detection
> logic
> > that is used in the SourceLevelDebugPkg.
> >
> >
> https://github.com/tianocore/edk2/blob/e2d3a25f1a313522
> 1a9c8061e1b8f90245d727eb/SourceLevelDebugPkg/Library/De
> bugAgent/DebugAgentCommon/DebugMp.c#L140
> >
> > Yes. CPUID can be used to determine availability of
> > MSR_IA32_APIC_BASE. That would be safer if the
> maximum
> > number of CPUs can start with a value of 1 and change
> to
> > a higher value later. But based on your analysis,
> > it looks like the max number of CPUs is known when
> this
> > function runs which is always after memory is
> discovered.
>
> The proposed patch is safe wrt. the PCD production-
> consumption sequence,
> yes.
>
> However, the patch is unsafe due to APs calling a PPI
> member function
> (namely, the PCD_PPI.Get32 function).
>
> To my understanding, APs may not call PPIs.
>
> > The MSR access is in the function GetCpuMpData(),
> which is
> > called from all the MP service functions. I was
> trying
> > to avoid an extra CPUID check on all those paths.
> >
> > I prefer the current patch if it is safe. Please let
> me
> > know if you think extra comments are required in the
> code
> > or the commit message.
>
> I think the patch is unsafe, because it is possible for
> both of the
> following conditions to hold, at the same time:
>
> - the function may be entered by an AP
> - the PCD may be dynamic
>
> That would lead to an AP calling
>
> (GetPcdPpiPointer ())->Get32 (TokenNumber)
>
> which I believe is forbidden.
>
>
> If the patch called FixedPcdGet32(), then the patch
> would be safe.
> Unfortunately, in that case, the patch wouldn't compile
> for OvmfPkg.
>
> If we can use a new PCD for this, such that
> UefiCpuPkg.dec does not
> permit platforms to pick "dynamic" for that PCD -- i.e.
> it would have to
> be Feature, Fixed, or Patch --, and then the patch is
> updated to call
> the appropriate flavor-specific PCD macro
> (FeaturePcdGet, PatchPcdGet*,
> FixedPcdGet*), then the patch will be fine.
>
> The point is that the "getting the PCD" action never
> enter a library
> function that is not explicitly MP-safe, nor enter a
> PPI member function.
>
> Thanks
> Laszlo
>
> >> -----Original Message-----
> >> From: devel@edk2.groups.io
> [mailto:devel@edk2.groups.io]
> >> On Behalf Of Laszlo Ersek
> >> Sent: Friday, April 26, 2019 12:25 PM
> >> To: Kinney, Michael D <michael.d.kinney@intel.com>;
> >> devel@edk2.groups.io
> >> Cc: Dong, Eric <eric.dong@intel.com>; Ni, Ray
> >> <ray.ni@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>
> >> Subject: Re: [edk2-devel] [Patch 2/4]
> >> UefiCpuPkg/MpInitLib: Avoid MSR_IA32_APIC_BASE for
> >> single core
> >>
> >> (+Jian)
> >>
> >> Hi Mike,
> >>
> >> thank you for the CC.
> >>
> >> On 04/25/19 19:53, Michael D Kinney wrote:
> >>> Avoid access to MSR_IA32_APIC_BASE that may not be
> >> supported
> >>> on single core CPUs. If
> >> PcdCpuMaxLogicalProcessorNumber is 1,
> >>> then there is only one CPU that must be the BSP.
> >>>
> >>> Cc: Eric Dong <eric.dong@intel.com>
> >>> Cc: Ray Ni <ray.ni@intel.com>
> >>> Cc: Laszlo Ersek <lersek@redhat.com>
> >>> Signed-off-by: Michael D Kinney
> >> <michael.d.kinney@intel.com>
> >>> ---
> >>> UefiCpuPkg/Library/MpInitLib/PeiMpLib.c | 15
> >> ++++++++++++++-
> >>> 1 file changed, 14 insertions(+), 1 deletion(-)
> >>>
> >>> diff --git
> a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
> >> b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
> >>> index 35dff91fd2..5488049c08 100644
> >>> --- a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
> >>> +++ b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
> >>> @@ -1,7 +1,7 @@
> >>> /** @file
> >>> MP initialize support functions for PEI phase.
> >>>
> >>> - Copyright (c) 2016 - 2018, Intel Corporation.
> All
> >> rights reserved.<BR>
> >>> + Copyright (c) 2016 - 2019, Intel Corporation.
> All
> >> rights reserved.<BR>
> >>> SPDX-License-Identifier: BSD-2-Clause-Patent
> >>>
> >>> **/
> >>> @@ -101,6 +101,19 @@ GetCpuMpData (
> >>> MSR_IA32_APIC_BASE_REGISTER ApicBaseMsr;
> >>> IA32_DESCRIPTOR Idtr;
> >>>
> >>> + //
> >>> + // If there is only 1 CPU, then it must be the
> BSP.
> >> This avoids an access to
> >>> + // MSR_IA32_APIC_BASE that may not be supported
> on
> >> single core CPUs.
> >>> + //
> >>> + if (PcdGet32 (PcdCpuMaxLogicalProcessorNumber)
> ==
> >> 1) {
> >>> + CpuMpData = GetCpuMpDataFromGuidedHob ();
> >>> + ASSERT (CpuMpData != NULL);
> >>> + return CpuMpData;
> >>> + }
> >>> +
> >>> + //
> >>> + // Otherwise use MSR_IA32_APIC_BASE to determine
> if
> >> the CPU is BSP or AP.
> >>> + //
> >>> ApicBaseMsr.Uint64 = AsmReadMsr64
> >> (MSR_IA32_APIC_BASE);
> >>> if (ApicBaseMsr.Bits.BSP == 1) {
> >>> CpuMpData = GetCpuMpDataFromGuidedHob ();
> >>>
> >>
> >> This patch leads me down on two paths:
> >>
> >> (1) Specifically regarding the code change. I think
> this
> >> patch is unsafe
> >> on platforms that dynamically set the PCD to a
> value
> >> larger than 1.
> >> (Including OVMF.)
> >>
> >> If the value is larger than 1, then the system
> has
> >> at least one AP,
> >> and the AP may enter the function. In addition,
> >> because the PCD is
> >> dynamic, the PcdGet32() call will invoke the PCD
> PPI
> >> (if I
> >> understand correctly), which is not allowed for
> an
> >> AP.
> >>
> >> Is it not possible to determine the availability
> of
> >> MSR_IA32_APIC_BASE from CPUID, or a different
> MSR?
> >>
> >>
> >> (2) More generally, this patch made me review
> >> OvmfPkg/PlatformPei:
> >>
> >> (a) OvmfPkg/PlatformPei sets the PCD in
> >> MaxCpuCountInitialization(),
> >>
> >> (b) later, OvmfPkg/PlatformPei publishes the
> >> permanent PEI RAM in
> >> PublishPeiMemory()
> >>
> >> (c) which in turn leads to the installation of
> >> gEfiPeiMemoryDiscoveredPpiGuid intto the PPI
> >> database, by the
> >> PEI Core
> >>
> >> (d) CpuMpPei can now be dispatched, because it
> has a
> >> depex on the
> >> "memory discovered" PPI
> >>
> >> (e) PeiMpInitLib, which is linked into CpuMpPei,
> can
> >> consume the PCD
> >> safely.
> >>
> >> I relied on this behavior in the following OVMF
> >> commit:
> >>
> >> commit 45a70db3c3a59b64e0f517870415963fbfacf507
> >> Author: Laszlo Ersek <lersek@redhat.com>
> >> Date: Thu Nov 24 15:18:44 2016 +0100
> >>
> >> OvmfPkg/PlatformPei: take VCPU count from
> QEMU
> >> and configure MpInitLib
> >>
> >> These settings will allow CpuMpPei and
> CpuDxe to
> >> wait for the initial AP
> >> check-ins exactly as long as necessary.
> >>
> >> It is safe to set
> >> PcdCpuMaxLogicalProcessorNumber and
> >> PcdCpuApInitTimeOutInMicroSeconds in
> >> OvmfPkg/PlatformPei.
> >> OvmfPkg/PlatformPei installs the permanent
> PEI
> >> RAM, producing
> >> gEfiPeiMemoryDiscoveredPpiGuid, and
> >> UefiCpuPkg/CpuMpPei has a depex on
> >> gEfiPeiMemoryDiscoveredPpiGuid.
> >>
> >> [...]
> >>
> >> Except... in commit 0a0d5296e448
> >> ("UefiCpuPkg/CpuMpPei: support
> >> stack guard feature", 2018-09-10), the DEPEX
> >> mentioned in step (d)
> >> was deleted.
> >>
> >> So now I got a bit nervous, because how are then
> the
> >> setting and
> >> reading of the PCD serialized between
> >> OvmfPkg/PlatformPei, and
> >> PeiMpInitLib in CpuMpPei?
> >>
> >> Luckily however, I think we're safe:
> >>
> >> - CpuMpPei itself doesn't consume the PCD,
> >>
> >> - MpInitLib consumes the PCD in several
> functions,
> >> but all clients
> >> of MpInitLib must call MpInitLibInitialize()
> >> first, before using
> >> other library APIs
> >>
> >> - CpuMpPei calls MpInitLibInitialize() in the
> >> InitializeCpuMpWorker() function
> >>
> >> - the InitializeCpuMpWorker() function is only
> >> called from the
> >> MemoryDiscoveredPpiNotifyCallback().
> >>
> >> So the PCD set/get order remains safe and
> >> deterministic. Even though
> >> CpuMpPei can now be dispatched before permanent
> >> memory is
> >> discovered, MpInitLibInitialize() -- and so the
> >> reading of the PCD
> >> -- is still delayed until after permanent PEI
> RAM is
> >> available.
> >> That's a relief.
> >>
> >> In fact, it looks like commit 0a0d5296e448
> >> ("UefiCpuPkg/CpuMpPei:
> >> support stack guard feature", 2018-09-10)
> delayed
> >> the entire
> >> original entry point of CpuMpPei into the
> "memory
> >> discovered"
> >> callback. That appears OK to me, it's just that
> the
> >> patch (~1000
> >> lines) could have been split at least in two:
> one
> >> patch could have
> >> implemented the "PPI DEPEX --> PPI notify"
> >> transformation, without
> >> other changes in behavior, and the second patch
> >> could have extended
> >> the (now delayed) startup logic with
> >> InitializeMpExceptionStackSwitchHandlers() &
> >> friends.
> >>
> >> Thanks
> >> Laszlo
> >>
> >>
> >
>
>
>
next prev parent reply other threads:[~2019-04-30 15:21 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-04-25 17:53 [Patch 0/4] Resolve Quark build and boot issues Michael D Kinney
2019-04-25 17:53 ` [Patch 1/4] MdePkg/BaseLib: Verify SSE2 support in IA32 AsmLfence() Michael D Kinney
2019-04-26 20:27 ` [edk2-devel] " Laszlo Ersek
2019-04-26 21:08 ` Brian J. Johnson
2019-04-29 11:15 ` Laszlo Ersek
2019-04-29 14:09 ` Liming Gao
2019-04-29 18:23 ` Michael D Kinney
2019-04-30 10:03 ` Laszlo Ersek
2019-04-28 8:28 ` Liming Gao
2019-04-25 17:53 ` [Patch 2/4] UefiCpuPkg/MpInitLib: Avoid MSR_IA32_APIC_BASE for single core Michael D Kinney
2019-04-25 18:07 ` Ni, Ray
2019-04-26 0:04 ` Dong, Eric
2019-04-26 19:24 ` Laszlo Ersek
2019-04-29 17:11 ` [edk2-devel] " Michael D Kinney
2019-04-30 10:02 ` Laszlo Ersek
2019-04-30 15:21 ` Michael D Kinney [this message]
2019-04-25 17:53 ` [Patch 3/4] QuarkSocPkg/SmmAccessDxe: Set region to UC on SMRAM close Michael D Kinney
2019-04-25 21:40 ` Steele, Kelly
2019-04-25 17:53 ` [Patch 4/4] QuarkPlatformPkg/PlatformInit: Resolve ResetSystemLib name collision Michael D Kinney
2019-04-25 21:40 ` Steele, Kelly
2019-04-28 8:25 ` [edk2-devel] " Liming Gao
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=E92EE9817A31E24EB0585FDF735412F5B9CA031C@ORSMSX113.amr.corp.intel.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