From nobody Thu May 2 21:25:00 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org; dmarc=fail(p=none dis=none) header.from=intel.com Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1530087205856572.2943787882539; Wed, 27 Jun 2018 01:13:25 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id CEB10202E5402; Wed, 27 Jun 2018 01:13:24 -0700 (PDT) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id BCDFE211F8864 for ; Wed, 27 Jun 2018 01:13:23 -0700 (PDT) Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 Jun 2018 01:13:23 -0700 Received: from ray-dev.ccr.corp.intel.com ([10.239.9.4]) by fmsmga005.fm.intel.com with ESMTP; 27 Jun 2018 01:13:21 -0700 X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=134.134.136.20; helo=mga02.intel.com; envelope-from=ruiyu.ni@intel.com; receiver=edk2-devel@lists.01.org X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,278,1526367600"; d="scan'208";a="240679837" From: Ruiyu Ni To: edk2-devel@lists.01.org Date: Wed, 27 Jun 2018 16:13:41 +0800 Message-Id: <20180627081341.289244-1-ruiyu.ni@intel.com> X-Mailer: git-send-email 2.16.1.windows.1 Subject: [edk2] [PATCH v2] UefiCpuPkg/MpInitLib: AP uses memory preceding IDT to store CpuMpData X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Laszlo Ersek , Jiewen Yao , Eric Dong , Fish Andrew MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Today's MpInitLib PEI implementation directly calls PeiServices->GetHobList() from AP which may cause racing issue. This patch fixes this issue by storing the CpuMpData to memory preceding IDT. Pointer to PeiServices pointer is stored there, so after AP procedure returns, the PeiServices pointer should be restored. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ruiyu Ni Cc: Jeff Fan Cc: Eric Dong Cc: Jiewen Yao Cc: Fish Andrew Cc: Laszlo Ersek --- UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 33 ++++++++++++++++- UefiCpuPkg/Library/MpInitLib/MpLib.c | 8 ++++ UefiCpuPkg/Library/MpInitLib/MpLib.h | 27 +++++++++++++- UefiCpuPkg/Library/MpInitLib/PeiMpLib.c | 66 +++++++++++++++++++++++++++++= ++-- 4 files changed, 129 insertions(+), 5 deletions(-) diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/M= pInitLib/DxeMpLib.c index e7ed21c6cd..26fead2c66 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c @@ -1,7 +1,7 @@ /** @file MP initialize support functions for DXE phase. =20 - Copyright (c) 2016, Intel Corporation. All rights reserved.
+ Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BS= D License which accompanies this distribution. The full text of the license may b= e found at @@ -75,6 +75,37 @@ SaveCpuMpData ( mCpuMpData =3D CpuMpData; } =20 +/** + Push the CpuMpData for AP to use. + + @param[in] The pointer to CPU MP Data structure will be pushed. + @param[out] The pointer to the context which will be passed to PopCpuMpD= ata(). + + @return The pointer value which was stored in where the CPU MP Data is = pushed. +**/ +VOID * +PushCpuMpData ( + IN CPU_MP_DATA *CpuMpData, + OUT VOID **Context + ) +{ + return NULL; +} + +/** + Pop the CpuMpData. + + @param[in] Pointer The pointer value which was stored in where the CPU = MP Data is pushed. + @param[in] Context The context of push/pop operation. +**/ +VOID +PopCpuMpData ( + IN VOID *Pointer, + IN VOID *Context + ) +{ =20 +} + /** Get available system memory below 1MB by specified size. =20 diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpIn= itLib/MpLib.c index f2ff40417a..b53d4c31c3 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -580,6 +580,8 @@ ApWakeupFunction ( CPU_INFO_IN_HOB *CpuInfoInHob; UINT64 ApTopOfStack; UINTN CurrentApicMode; + VOID *OriginalValue; + VOID *Context; =20 // // AP finished assembly code and begin to execute C code @@ -659,8 +661,14 @@ ApWakeupFunction ( EnableDebugAgent (); // // Invoke AP function here + // Use a BSP owned area (PeiServices Pointer storage) to store t= he CpuMpData. + // It's required in PEI phase because CpuMpData cannot be cached= in global variable as in DXE phase. + // DXE version of Pushxxx andPopxxx is dummy implementation. // + OriginalValue =3D PushCpuMpData (CpuMpData, &Context); Procedure (Parameter); + PopCpuMpData (OriginalValue, Context); + CpuInfoInHob =3D (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoI= nHob; if (CpuMpData->SwitchBspFlag) { // diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpIn= itLib/MpLib.h index e7f9a4de0a..270d62ff20 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -1,7 +1,7 @@ /** @file Common header file for MP Initialize Library. =20 - Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.
+ Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BS= D License which accompanies this distribution. The full text of the license may b= e found at @@ -321,6 +321,31 @@ SaveCpuMpData ( IN CPU_MP_DATA *CpuMpData ); =20 +/** + Push the CpuMpData for AP to use. + + @param[in] The pointer to CPU MP Data structure will be pushed. + @param[out] The pointer to the context which will be passed to PopCpuMpD= ata(). + + @return The pointer value which was stored in where the CPU MP Data is = pushed. +**/ +VOID * +PushCpuMpData ( + IN CPU_MP_DATA *CpuMpData, + OUT VOID **Context + ); + +/** + Pop the CpuMpData. + + @param[in] Pointer The pointer value which was stored in where the CPU = MP Data is pushed. + @param[in] Context The context of push/pop operation. +**/ +VOID +PopCpuMpData ( + IN VOID *Pointer, + IN VOID *Context + ); =20 /** Get available system memory below 1MB by specified size. diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c b/UefiCpuPkg/Library/M= pInitLib/PeiMpLib.c index 791ae9db6e..daaceafb00 100644 --- a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c @@ -27,6 +27,9 @@ EnableDebugAgent ( =20 /** Get pointer to CPU MP Data structure. + For BSP, the pointer is retrieved from HOB. + For AP, the pointer is retrieved from the location which stores the PeiS= ervices pointer. + It's safe because BSP is blocking and has no chance to use PeiServices p= ointer when AP is executing. =20 @return The pointer to CPU MP Data structure. **/ @@ -35,9 +38,17 @@ GetCpuMpData ( VOID ) { - CPU_MP_DATA *CpuMpData; - - CpuMpData =3D GetCpuMpDataFromGuidedHob (); + CPU_MP_DATA *CpuMpData; + MSR_IA32_APIC_BASE_REGISTER ApicBaseMsr; + IA32_DESCRIPTOR Idtr; + + ApicBaseMsr.Uint64 =3D AsmReadMsr64 (MSR_IA32_APIC_BASE); + if (ApicBaseMsr.Bits.BSP =3D=3D 1) { + CpuMpData =3D GetCpuMpDataFromGuidedHob (); + } else { + AsmReadIdtr (&Idtr); + CpuMpData =3D (CPU_MP_DATA *)(*(UINTN *) (Idtr.Base - sizeof (UINTN))); + } ASSERT (CpuMpData !=3D NULL); return CpuMpData; } @@ -64,6 +75,55 @@ SaveCpuMpData ( ); } =20 +/** + Push the CpuMpData for AP to use. + + @param[in] The pointer to CPU MP Data structure will be pushed. + @param[out] The pointer to the context which will be passed to PopCpuMpD= ata(). + + @return The pointer value which was stored in where the CPU MP Data is = pushed. +**/ +VOID * +PushCpuMpData ( + IN CPU_MP_DATA *CpuMpData, + OUT VOID **Context + ) +{ + VOID *OriginalValue; + IA32_DESCRIPTOR Idtr; + + if (AcquireSpinLockOrFail (&CpuMpData->MpLock)) { + AsmReadIdtr (&Idtr); + *Context =3D (VOID *) (Idtr.Base - sizeof (UINTN)); + OriginalValue =3D *(VOID **)(*Context); + *(CPU_MP_DATA **)(*Context) =3D CpuMpData; + return OriginalValue; + } else { + *Context =3D NULL; + return NULL; + } +} + +/** + Pop the CpuMpData. + + @param[in] Pointer The pointer value which was stored in where the CPU = MP Data is pushed. + @param[in] Context The context of push/pop operation. +**/ +VOID +PopCpuMpData ( + IN VOID *Pointer, + IN VOID *Context + ) +{ + CPU_MP_DATA *CpuMpData; + if (Context !=3D NULL) { + CpuMpData =3D *(CPU_MP_DATA **)Context; + *(VOID **)Context =3D Pointer; + ReleaseSpinLock (&CpuMpData->MpLock); + } +} + /** Check if AP wakeup buffer is overlapped with existing allocated buffer. =20 --=20 2.16.1.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel