From nobody Tue Feb 10 15:29:41 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+82362+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one); dmarc=pass(p=none dis=none) header.from=groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1634672401975787.9045660161504; Tue, 19 Oct 2021 12:40:01 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id lmauYY1788612xfFS6odXEMH; Tue, 19 Oct 2021 12:40:01 -0700 X-Received: from NAM10-MW2-obe.outbound.protection.outlook.com (NAM10-MW2-obe.outbound.protection.outlook.com [40.107.94.57]) by mx.groups.io with SMTP id smtpd.web12.15079.1634672400828712444 for ; Tue, 19 Oct 2021 12:40:01 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=fyaW8V6OMXq+XGvAl/XuEnaNTMo8fSGItS8tK9TQNUV8fUSgt/SyRL7HWtxs0F2gcfGNWThhawiBxt3HfXzKp/KkhiLdgVj7TlmT8ENb8/Nrcwo2ZX5f1A2F8L5ZmGvQlCKxihttzBZOguvzpuTgdGzk5Gf1oV9bhm/MvRKEZ6U5hss8fNwH7gfhGaYhTuEF591z2n6hJlmKlmG1ih+GsMTL8LTq54yuZGjPcGlUjaAqlJ7pnLNmT3MIqzQ9ig2TW0GDaZUBTRqd+DxMeuZ2cE1XOwaiPL1lfJz7fFjO/oSgdIRHbwuxOVxiurTuvLOw0INxzEBOhAub/cQwxmqJ+Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=kQQ2npg0HTGsrgAOu5nmPFM7uCJk7y+ygvYrUxnJQNA=; b=jgH4TyDIqx0mfnBWdQreV8I+30TzDyYxFw4mOMcyc/8WFBpRG1uHQ3jN0y8FCLjXQ0KdP8SkdxNxOozVpT0M/LY+CrJIGvv/eNj13ktzZglgw6kaXV1abQozaL/y9QAFfTWEo3MMSCyA1azJ8b0HaGXiTvsKLCLc/O5W4heZsoRA1oQNPj1PirkzkOI2wINfDySNyuxl3frnbxWwcP6SAO+T6kJIRgLPNJ8TOsMBiQDqeIEUyJdpQDzjRzgGvr3aFl7wHPiDQx6hWyLbMvA4xyLbJkWfZF97angOeRFYfq6hOerL+lW/P/saShU9NanUNgVHrQEfhMokJHvG/9cGvw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none X-Received: from MWHPR14CA0070.namprd14.prod.outlook.com (2603:10b6:300:81::32) by DM5PR12MB1451.namprd12.prod.outlook.com (2603:10b6:4:d::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4608.18; Tue, 19 Oct 2021 19:39:58 +0000 X-Received: from CO1NAM11FT004.eop-nam11.prod.protection.outlook.com (2603:10b6:300:81:cafe::79) by MWHPR14CA0070.outlook.office365.com (2603:10b6:300:81::32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4608.15 via Frontend Transport; Tue, 19 Oct 2021 19:39:57 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=pass action=none header.from=amd.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+82362+1787277+3901457@groups.io; helo=mail02.groups.io; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; X-Received: from SATLEXMB04.amd.com (165.204.84.17) by CO1NAM11FT004.mail.protection.outlook.com (10.13.175.89) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.4608.15 via Frontend Transport; Tue, 19 Oct 2021 19:39:57 +0000 X-Received: from sbrijesh-desktop.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.15; Tue, 19 Oct 2021 14:39:52 -0500 From: "Brijesh Singh via groups.io" To: CC: James Bottomley , Min Xu , "Jiewen Yao" , Tom Lendacky , "Jordan Justen" , Ard Biesheuvel , Erdem Aktas , "Michael Roth" , Gerd Hoffmann , Brijesh Singh , Eric Dong , Ray Ni , Rahul Kumar , Michael Roth , Jiewen Yao Subject: [edk2-devel] [PATCH v10 02/32] UefiCpuPkg/MpInitLib: move SEV specific routines in AmdSev.c Date: Tue, 19 Oct 2021 14:39:04 -0500 Message-ID: <20211019193934.1052465-3-brijesh.singh@amd.com> In-Reply-To: <20211019193934.1052465-1-brijesh.singh@amd.com> References: <20211019193934.1052465-1-brijesh.singh@amd.com> MIME-Version: 1.0 X-Originating-IP: [10.180.168.240] X-ClientProxiedBy: SATLEXMB04.amd.com (10.181.40.145) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: bc40afdb-fb96-4533-1044-08d993383b81 X-MS-TrafficTypeDiagnostic: DM5PR12MB1451: X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:9508; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Message-Info: ACnVhYIWI8wYE+3DSEt9ktdIrveITjy00NUEUwJL8zgm8dHiZOKJ7Zrh+bbXNJEXLLxmncoqLzzSuZaDbljgHB3ssG++6j3Nvuhgkw2GahG3nDOGe+Exbd7Q4x5D/inbyvkwycddmnrBv+U1ObvnvbsOeuBN3t1OGixsR6MP4gXmRZF+F8gRP7yDNAHv3yOGpaU4i3ARpytUEzszrOI0ygZnl/61EVeMOGJJ4ia2Q2+3h3s3jf1ZnpHcckTunmVJsVs2+hjAAnr+wYh7ipPVyJufsMpsco1+ruBEW/TZXCZq99W6SCLdnLCT4ltZlmUqRrhVBoFtq0ZUxTpC+0526dY8/tBdAQQuW3fw1CdelQvFQ41fPVhO1ITu0V+f2xClUH8E3ZcuIr2kwuVcc5+wh3C10H9XsKR05BDqRjD12qBaj9DLFXOUHOL9nnYFJeb7urRTbQ+1HIGxKNIS0r55hiZLnvBXp9r7Xroodtk5x4lZZ0WCQQZI3Jl1T21wCBP1VFyvQHqOtoq9PtAYZfSiEl0TXb9TbOdIGRDCJ5deUQgSQsyGyX77ZsfRJ5VhEOpu8HzgPodqssKCQPRrczN2ul/tQG0FKYp4izSLvu59O2o8ZkklFLwVjbS1XdJQ6zBmPFRfRvpEOCMiBIlEDxbL9NEJeLNHMOm3hbMs6zcsiaBdrpe5nxk5YcQW1llaBQCmerP/C3RPCK4AbRAY1Bs6m32OGLKVzKL46g6/r2Sbg2yy74awzpkcpkmDkZsBMVgFycFA2uyLb6sF6EYvW4hdy84DO/9hO28dAh6/Z1FstIen/pvqvoUTxCTKzytsC1UY X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Oct 2021 19:39:57.3892 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: bc40afdb-fb96-4533-1044-08d993383b81 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CO1NAM11FT004.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR12MB1451 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,brijesh.singh@amd.com X-Gm-Message-State: ZoXF1RSCmKFcpDHADdgHwS2fx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1634672401; bh=SQgVbTIi8O9O3TGZ4YwByAV8NcKAOCYnMxFQ0z5xN6g=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=E72qTiGDi+a6HNxQvy3rrJeYFMdbWgNdlCENjjHqLcGvhzOfG5uAESeSZfvpb7Rjmcu BBubz79l1HO5pA2QkNo0cAHE8wb1Pmbtpbijq2kovAksAuZtsQatdPVpo6PlkH3wAa7Ra w8mRXZei4YAp04fPmSQ3yr+Lc4/TumahySA= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1634672402564100009 Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3275 Move all the SEV specific function in AmdSev.c. No functional change intended. Cc: Eric Dong Cc: Ray Ni Cc: Rahul Kumar Cc: Michael Roth Cc: James Bottomley Cc: Min Xu Cc: Jiewen Yao Cc: Tom Lendacky Cc: Jordan Justen Cc: Ard Biesheuvel Cc: Erdem Aktas Cc: Gerd Hoffmann Acked-by: Gerd Hoffmann Suggested-by: Jiewen Yao Signed-off-by: Brijesh Singh --- UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf | 1 + UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf | 1 + UefiCpuPkg/Library/MpInitLib/MpLib.h | 33 +++ UefiCpuPkg/Library/MpInitLib/AmdSev.c | 239 ++++++++++++++++++ UefiCpuPkg/Library/MpInitLib/MpLib.c | 218 +--------------- UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm | 119 +++++++++ UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm | 100 ++------ 7 files changed, 413 insertions(+), 298 deletions(-) create mode 100644 UefiCpuPkg/Library/MpInitLib/AmdSev.c create mode 100644 UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf b/UefiCpuPkg/Lib= rary/MpInitLib/DxeMpInitLib.inf index d34419c2a524..6e510aa89120 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf @@ -28,6 +28,7 @@ [Sources.X64] X64/MpFuncs.nasm =20 [Sources.common] + AmdSev.c MpEqu.inc DxeMpLib.c MpLib.c diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf b/UefiCpuPkg/Lib= rary/MpInitLib/PeiMpInitLib.inf index 36fcb96b5852..2cbd9b8b8acc 100644 --- a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf +++ b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf @@ -28,6 +28,7 @@ [Sources.X64] X64/MpFuncs.nasm =20 [Sources.common] + AmdSev.c MpEqu.inc PeiMpLib.c MpLib.c diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpIn= itLib/MpLib.h index e88a5355c983..3d4446df8ce6 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -34,6 +34,9 @@ #include #include =20 +#include +#include + #include =20 #define WAKEUP_AP_SIGNAL SIGNATURE_32 ('S', 'T', 'A', 'P') @@ -741,5 +744,35 @@ PlatformShadowMicrocode ( IN OUT CPU_MP_DATA *CpuMpData ); =20 +/** + Allocate the SEV-ES AP jump table buffer. + + @param[in, out] CpuMpData The pointer to CPU MP Data structure. +**/ +VOID +AllocateSevEsAPMemory ( + IN OUT CPU_MP_DATA *CpuMpData + ); + +/** + Program the SEV-ES AP jump table buffer. + + @param[in] SipiVector The SIPI vector used for the AP Reset +**/ +VOID +SetSevEsJumpTable ( + IN UINTN SipiVector + ); + +/** + The function puts the AP in halt loop. + + @param[in] CpuMpData The pointer to CPU MP Data structure. +**/ +VOID +SevEsPlaceApHlt ( + CPU_MP_DATA *CpuMpData + ); + #endif =20 diff --git a/UefiCpuPkg/Library/MpInitLib/AmdSev.c b/UefiCpuPkg/Library/MpI= nitLib/AmdSev.c new file mode 100644 index 000000000000..7dbf117c2b71 --- /dev/null +++ b/UefiCpuPkg/Library/MpInitLib/AmdSev.c @@ -0,0 +1,239 @@ +/** @file + CPU MP Initialize helper function for AMD SEV. + + Copyright (c) 2021, AMD Inc. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MpLib.h" +#include + +/** + Get Protected mode code segment with 16-bit default addressing + from current GDT table. + + @return Protected mode 16-bit code segment value. +**/ +STATIC +UINT16 +GetProtectedMode16CS ( + VOID + ) +{ + IA32_DESCRIPTOR GdtrDesc; + IA32_SEGMENT_DESCRIPTOR *GdtEntry; + UINTN GdtEntryCount; + UINT16 Index; + + Index =3D (UINT16) -1; + AsmReadGdtr (&GdtrDesc); + GdtEntryCount =3D (GdtrDesc.Limit + 1) / sizeof (IA32_SEGMENT_DESCRIPTOR= ); + GdtEntry =3D (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base; + for (Index =3D 0; Index < GdtEntryCount; Index++) { + if (GdtEntry->Bits.L =3D=3D 0 && + GdtEntry->Bits.DB =3D=3D 0 && + GdtEntry->Bits.Type > 8) { + break; + } + GdtEntry++; + } + ASSERT (Index !=3D GdtEntryCount); + return Index * 8; +} + +/** + Get Protected mode code segment with 32-bit default addressing + from current GDT table. + + @return Protected mode 32-bit code segment value. +**/ +STATIC +UINT16 +GetProtectedMode32CS ( + VOID + ) +{ + IA32_DESCRIPTOR GdtrDesc; + IA32_SEGMENT_DESCRIPTOR *GdtEntry; + UINTN GdtEntryCount; + UINT16 Index; + + Index =3D (UINT16) -1; + AsmReadGdtr (&GdtrDesc); + GdtEntryCount =3D (GdtrDesc.Limit + 1) / sizeof (IA32_SEGMENT_DESCRIPTOR= ); + GdtEntry =3D (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base; + for (Index =3D 0; Index < GdtEntryCount; Index++) { + if (GdtEntry->Bits.L =3D=3D 0 && + GdtEntry->Bits.DB =3D=3D 1 && + GdtEntry->Bits.Type > 8) { + break; + } + GdtEntry++; + } + ASSERT (Index !=3D GdtEntryCount); + return Index * 8; +} + +/** + Reset an AP when in SEV-ES mode. + + If successful, this function never returns. + + @param[in] Ghcb Pointer to the GHCB + @param[in] CpuMpData Pointer to CPU MP Data + +**/ +VOID +MpInitLibSevEsAPReset ( + IN GHCB *Ghcb, + IN CPU_MP_DATA *CpuMpData + ) +{ + EFI_STATUS Status; + UINTN ProcessorNumber; + UINT16 Code16, Code32; + AP_RESET *APResetFn; + UINTN BufferStart; + UINTN StackStart; + + Status =3D GetProcessorNumber (CpuMpData, &ProcessorNumber); + ASSERT_EFI_ERROR (Status); + + Code16 =3D GetProtectedMode16CS (); + Code32 =3D GetProtectedMode32CS (); + + if (CpuMpData->WakeupBufferHigh !=3D 0) { + APResetFn =3D (AP_RESET *) (CpuMpData->WakeupBufferHigh + CpuMpData->A= ddressMap.SwitchToRealNoNxOffset); + } else { + APResetFn =3D (AP_RESET *) (CpuMpData->MpCpuExchangeInfo->BufferStart = + CpuMpData->AddressMap.SwitchToRealOffset); + } + + BufferStart =3D CpuMpData->MpCpuExchangeInfo->BufferStart; + StackStart =3D CpuMpData->SevEsAPResetStackStart - + (AP_RESET_STACK_SIZE * ProcessorNumber); + + // + // This call never returns. + // + APResetFn (BufferStart, Code16, Code32, StackStart); +} + +/** + Allocate the SEV-ES AP jump table buffer. + + @param[in, out] CpuMpData The pointer to CPU MP Data structure. +**/ +VOID +AllocateSevEsAPMemory ( + IN OUT CPU_MP_DATA *CpuMpData + ) +{ + if (CpuMpData->SevEsAPBuffer =3D=3D (UINTN) -1) { + CpuMpData->SevEsAPBuffer =3D + CpuMpData->SevEsIsEnabled ? GetSevEsAPMemory () : 0; + } +} + +/** + Program the SEV-ES AP jump table buffer. + + @param[in] SipiVector The SIPI vector used for the AP Reset +**/ +VOID +SetSevEsJumpTable ( + IN UINTN SipiVector + ) +{ + SEV_ES_AP_JMP_FAR *JmpFar; + UINT32 Offset, InsnByte; + UINT8 LoNib, HiNib; + + JmpFar =3D (SEV_ES_AP_JMP_FAR *) (UINTN) FixedPcdGet32 (PcdSevEsWorkArea= Base); + ASSERT (JmpFar !=3D NULL); + + // + // Obtain the address of the Segment/Rip location in the workarea. + // This will be set to a value derived from the SIPI vector and will + // be the memory address used for the far jump below. + // + Offset =3D FixedPcdGet32 (PcdSevEsWorkAreaBase); + Offset +=3D sizeof (JmpFar->InsnBuffer); + LoNib =3D (UINT8) Offset; + HiNib =3D (UINT8) (Offset >> 8); + + // + // Program the workarea (which is the initial AP boot address) with + // far jump to the SIPI vector (where XX and YY represent the + // address of where the SIPI vector is stored. + // + // JMP FAR [CS:XXYY] =3D> 2E FF 2E YY XX + // + InsnByte =3D 0; + JmpFar->InsnBuffer[InsnByte++] =3D 0x2E; // CS override prefix + JmpFar->InsnBuffer[InsnByte++] =3D 0xFF; // JMP (FAR) + JmpFar->InsnBuffer[InsnByte++] =3D 0x2E; // ModRM (JMP memory location) + JmpFar->InsnBuffer[InsnByte++] =3D LoNib; // YY offset ... + JmpFar->InsnBuffer[InsnByte++] =3D HiNib; // XX offset ... + + // + // Program the Segment/Rip based on the SIPI vector (always at least + // 16-byte aligned, so Rip is set to 0). + // + JmpFar->Rip =3D 0; + JmpFar->Segment =3D (UINT16) (SipiVector >> 4); +} + +/** + The function puts the AP in halt loop. + + @param[in] CpuMpData The pointer to CPU MP Data structure. +**/ +VOID +SevEsPlaceApHlt ( + CPU_MP_DATA *CpuMpData + ) +{ + MSR_SEV_ES_GHCB_REGISTER Msr; + GHCB *Ghcb; + UINT64 Status; + BOOLEAN DoDecrement; + BOOLEAN InterruptState; + + DoDecrement =3D (BOOLEAN) (CpuMpData->InitFlag =3D=3D ApInitConfig); + + while (TRUE) { + Msr.GhcbPhysicalAddress =3D AsmReadMsr64 (MSR_SEV_ES_GHCB); + Ghcb =3D Msr.Ghcb; + + VmgInit (Ghcb, &InterruptState); + + if (DoDecrement) { + DoDecrement =3D FALSE; + + // + // Perform the delayed decrement just before issuing the first + // VMGEXIT with AP_RESET_HOLD. + // + InterlockedDecrement ((UINT32 *) &CpuMpData->MpCpuExchangeInfo->NumA= psExecuting); + } + + Status =3D VmgExit (Ghcb, SVM_EXIT_AP_RESET_HOLD, 0, 0); + if ((Status =3D=3D 0) && (Ghcb->SaveArea.SwExitInfo2 !=3D 0)) { + VmgDone (Ghcb, InterruptState); + break; + } + + VmgDone (Ghcb, InterruptState); + } + + // + // Awakened in a new phase? Use the new CpuMpData + // + if (CpuMpData->NewCpuMpData !=3D NULL) { + CpuMpData =3D CpuMpData->NewCpuMpData; + } + + MpInitLibSevEsAPReset (Ghcb, CpuMpData); +} diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpIn= itLib/MpLib.c index b9a06747edbf..890945bc5994 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -596,117 +596,6 @@ InitializeApData ( SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle); } =20 -/** - Get Protected mode code segment with 16-bit default addressing - from current GDT table. - - @return Protected mode 16-bit code segment value. -**/ -STATIC -UINT16 -GetProtectedMode16CS ( - VOID - ) -{ - IA32_DESCRIPTOR GdtrDesc; - IA32_SEGMENT_DESCRIPTOR *GdtEntry; - UINTN GdtEntryCount; - UINT16 Index; - - Index =3D (UINT16) -1; - AsmReadGdtr (&GdtrDesc); - GdtEntryCount =3D (GdtrDesc.Limit + 1) / sizeof (IA32_SEGMENT_DESCRIPTOR= ); - GdtEntry =3D (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base; - for (Index =3D 0; Index < GdtEntryCount; Index++) { - if (GdtEntry->Bits.L =3D=3D 0 && - GdtEntry->Bits.DB =3D=3D 0 && - GdtEntry->Bits.Type > 8) { - break; - } - GdtEntry++; - } - ASSERT (Index !=3D GdtEntryCount); - return Index * 8; -} - -/** - Get Protected mode code segment with 32-bit default addressing - from current GDT table. - - @return Protected mode 32-bit code segment value. -**/ -STATIC -UINT16 -GetProtectedMode32CS ( - VOID - ) -{ - IA32_DESCRIPTOR GdtrDesc; - IA32_SEGMENT_DESCRIPTOR *GdtEntry; - UINTN GdtEntryCount; - UINT16 Index; - - Index =3D (UINT16) -1; - AsmReadGdtr (&GdtrDesc); - GdtEntryCount =3D (GdtrDesc.Limit + 1) / sizeof (IA32_SEGMENT_DESCRIPTOR= ); - GdtEntry =3D (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base; - for (Index =3D 0; Index < GdtEntryCount; Index++) { - if (GdtEntry->Bits.L =3D=3D 0 && - GdtEntry->Bits.DB =3D=3D 1 && - GdtEntry->Bits.Type > 8) { - break; - } - GdtEntry++; - } - ASSERT (Index !=3D GdtEntryCount); - return Index * 8; -} - -/** - Reset an AP when in SEV-ES mode. - - If successful, this function never returns. - - @param[in] Ghcb Pointer to the GHCB - @param[in] CpuMpData Pointer to CPU MP Data - -**/ -STATIC -VOID -MpInitLibSevEsAPReset ( - IN GHCB *Ghcb, - IN CPU_MP_DATA *CpuMpData - ) -{ - EFI_STATUS Status; - UINTN ProcessorNumber; - UINT16 Code16, Code32; - AP_RESET *APResetFn; - UINTN BufferStart; - UINTN StackStart; - - Status =3D GetProcessorNumber (CpuMpData, &ProcessorNumber); - ASSERT_EFI_ERROR (Status); - - Code16 =3D GetProtectedMode16CS (); - Code32 =3D GetProtectedMode32CS (); - - if (CpuMpData->WakeupBufferHigh !=3D 0) { - APResetFn =3D (AP_RESET *) (CpuMpData->WakeupBufferHigh + CpuMpData->A= ddressMap.SwitchToRealNoNxOffset); - } else { - APResetFn =3D (AP_RESET *) (CpuMpData->MpCpuExchangeInfo->BufferStart = + CpuMpData->AddressMap.SwitchToRealOffset); - } - - BufferStart =3D CpuMpData->MpCpuExchangeInfo->BufferStart; - StackStart =3D CpuMpData->SevEsAPResetStackStart - - (AP_RESET_STACK_SIZE * ProcessorNumber); - - // - // This call never returns. - // - APResetFn (BufferStart, Code16, Code32, StackStart); -} - /** This function will be called from AP reset code if BSP uses WakeUpAP. =20 @@ -884,47 +773,7 @@ ApWakeupFunction ( while (TRUE) { DisableInterrupts (); if (CpuMpData->SevEsIsEnabled) { - MSR_SEV_ES_GHCB_REGISTER Msr; - GHCB *Ghcb; - UINT64 Status; - BOOLEAN DoDecrement; - BOOLEAN InterruptState; - - DoDecrement =3D (BOOLEAN) (CpuMpData->InitFlag =3D=3D ApInitConf= ig); - - while (TRUE) { - Msr.GhcbPhysicalAddress =3D AsmReadMsr64 (MSR_SEV_ES_GHCB); - Ghcb =3D Msr.Ghcb; - - VmgInit (Ghcb, &InterruptState); - - if (DoDecrement) { - DoDecrement =3D FALSE; - - // - // Perform the delayed decrement just before issuing the fir= st - // VMGEXIT with AP_RESET_HOLD. - // - InterlockedDecrement ((UINT32 *) &CpuMpData->MpCpuExchangeIn= fo->NumApsExecuting); - } - - Status =3D VmgExit (Ghcb, SVM_EXIT_AP_RESET_HOLD, 0, 0); - if ((Status =3D=3D 0) && (Ghcb->SaveArea.SwExitInfo2 !=3D 0)) { - VmgDone (Ghcb, InterruptState); - break; - } - - VmgDone (Ghcb, InterruptState); - } - - // - // Awakened in a new phase? Use the new CpuMpData - // - if (CpuMpData->NewCpuMpData !=3D NULL) { - CpuMpData =3D CpuMpData->NewCpuMpData; - } - - MpInitLibSevEsAPReset (Ghcb, CpuMpData); + SevEsPlaceApHlt (CpuMpData); } else { CpuSleep (); } @@ -1252,71 +1101,6 @@ FreeResetVector ( } } =20 -/** - Allocate the SEV-ES AP jump table buffer. - - @param[in, out] CpuMpData The pointer to CPU MP Data structure. -**/ -VOID -AllocateSevEsAPMemory ( - IN OUT CPU_MP_DATA *CpuMpData - ) -{ - if (CpuMpData->SevEsAPBuffer =3D=3D (UINTN) -1) { - CpuMpData->SevEsAPBuffer =3D - CpuMpData->SevEsIsEnabled ? GetSevEsAPMemory () : 0; - } -} - -/** - Program the SEV-ES AP jump table buffer. - - @param[in] SipiVector The SIPI vector used for the AP Reset -**/ -VOID -SetSevEsJumpTable ( - IN UINTN SipiVector - ) -{ - SEV_ES_AP_JMP_FAR *JmpFar; - UINT32 Offset, InsnByte; - UINT8 LoNib, HiNib; - - JmpFar =3D (SEV_ES_AP_JMP_FAR *) (UINTN) FixedPcdGet32 (PcdSevEsWorkArea= Base); - ASSERT (JmpFar !=3D NULL); - - // - // Obtain the address of the Segment/Rip location in the workarea. - // This will be set to a value derived from the SIPI vector and will - // be the memory address used for the far jump below. - // - Offset =3D FixedPcdGet32 (PcdSevEsWorkAreaBase); - Offset +=3D sizeof (JmpFar->InsnBuffer); - LoNib =3D (UINT8) Offset; - HiNib =3D (UINT8) (Offset >> 8); - - // - // Program the workarea (which is the initial AP boot address) with - // far jump to the SIPI vector (where XX and YY represent the - // address of where the SIPI vector is stored. - // - // JMP FAR [CS:XXYY] =3D> 2E FF 2E YY XX - // - InsnByte =3D 0; - JmpFar->InsnBuffer[InsnByte++] =3D 0x2E; // CS override prefix - JmpFar->InsnBuffer[InsnByte++] =3D 0xFF; // JMP (FAR) - JmpFar->InsnBuffer[InsnByte++] =3D 0x2E; // ModRM (JMP memory location) - JmpFar->InsnBuffer[InsnByte++] =3D LoNib; // YY offset ... - JmpFar->InsnBuffer[InsnByte++] =3D HiNib; // XX offset ... - - // - // Program the Segment/Rip based on the SIPI vector (always at least - // 16-byte aligned, so Rip is set to 0). - // - JmpFar->Rip =3D 0; - JmpFar->Segment =3D (UINT16) (SipiVector >> 4); -} - /** This function will be called by BSP to wakeup AP. =20 diff --git a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm b/UefiCpuPkg/Libr= ary/MpInitLib/X64/AmdSev.nasm new file mode 100644 index 000000000000..0ccafe25eca4 --- /dev/null +++ b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm @@ -0,0 +1,119 @@ +;-------------------------------------------------------------------------= ----- ; +; Copyright (c) 2021, AMD Inc. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; AmdSev.nasm +; +; Abstract: +; +; This provides helper used by the MpFunc.nasm. If AMD SEV-ES is active +; then helpers perform the additional setups (such as GHCB). +; +;-------------------------------------------------------------------------= ------ + +%define SIZE_4KB 0x1000 + +; +; The function checks whether SEV-ES is enabled, if enabled +; then setup the GHCB page. +; +SevEsSetupGhcb: + lea edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (SevEsIsEnabled)] + cmp byte [edi], 1 ; SevEsIsEnabled + jne SevEsSetupGhcbExit + + ; + ; program GHCB + ; Each page after the GHCB is a per-CPU page, so the calculation pro= grams + ; a GHCB to be every 8KB. + ; + mov eax, SIZE_4KB + shl eax, 1 ; EAX =3D SIZE_4K * 2 + mov ecx, ebx + mul ecx ; EAX =3D SIZE_4K * 2 * C= puNumber + mov edi, esi + add edi, MP_CPU_EXCHANGE_INFO_FIELD (GhcbBase) + add rax, qword [edi] + mov rdx, rax + shr rdx, 32 + mov rcx, 0xc0010130 + wrmsr + +SevEsSetupGhcbExit: + OneTimeCallRet SevEsSetupGhcb + +; +; The function checks whether SEV-ES is enabled, if enabled, use +; the GHCB +; +SevEsGetApicId: + lea edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (SevEsIsEnabled)] + cmp byte [edi], 1 ; SevEsIsEnabled + jne SevEsGetApicIdExit + + ; + ; Since we don't have a stack yet, we can't take a #VC + ; exception. Use the GHCB protocol to perform the CPUID + ; calls. + ; + mov rcx, 0xc0010130 + rdmsr + shl rdx, 32 + or rax, rdx + mov rdi, rax ; RDI now holds the original GHCB GPA + + mov rdx, 0 ; CPUID function 0 + mov rax, 0 ; RAX register requested + or rax, 4 + wrmsr + rep vmmcall + rdmsr + cmp edx, 0bh + jb NoX2ApicSevEs ; CPUID level below CPUID_EXTENDED_TOP= OLOGY + + mov rdx, 0bh ; CPUID function 0x0b + mov rax, 040000000h ; RBX register requested + or rax, 4 + wrmsr + rep vmmcall + rdmsr + test edx, 0ffffh + jz NoX2ApicSevEs ; CPUID.0BH:EBX[15:0] is zero + + mov rdx, 0bh ; CPUID function 0x0b + mov rax, 0c0000000h ; RDX register requested + or rax, 4 + wrmsr + rep vmmcall + rdmsr + + ; Processor is x2APIC capable; 32-bit x2APIC ID is now in EDX + jmp RestoreGhcb + +NoX2ApicSevEs: + ; Processor is not x2APIC capable, so get 8-bit APIC ID + mov rdx, 1 ; CPUID function 1 + mov rax, 040000000h ; RBX register requested + or rax, 4 + wrmsr + rep vmmcall + rdmsr + shr edx, 24 + +RestoreGhcb: + mov rbx, rdx ; Save x2APIC/APIC ID + + mov rdx, rdi ; RDI holds the saved GHCB GPA + shr rdx, 32 + mov eax, edi + wrmsr + + mov rdx, rbx + + ; x2APIC ID or APIC ID is in EDX + jmp GetProcessorNumber + +SevEsGetApicIdExit: + OneTimeCallRet SevEsGetApicId diff --git a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm b/UefiCpuPkg/Lib= rary/MpInitLib/X64/MpFuncs.nasm index 50df802d1fca..f7f2937fafad 100644 --- a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm +++ b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm @@ -15,6 +15,15 @@ %include "MpEqu.inc" extern ASM_PFX(InitializeFloatingPointUnits) =20 +%macro OneTimeCall 1 + jmp %1 +%1 %+ OneTimerCallReturn: +%endmacro + +%macro OneTimeCallRet 1 + jmp %1 %+ OneTimerCallReturn +%endmacro + DEFAULT REL =20 SECTION .text @@ -144,6 +153,12 @@ SkipEnable5LevelPaging: jmp far [edi] =20 BITS 64 + +; +; Required for the AMD SEV helper functions +; +%include "AmdSev.nasm" + LongModeStart: mov esi, ebx lea edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (InitFlag)] @@ -175,94 +190,17 @@ LongModeStart: add rax, qword [edi] mov rsp, rax =20 - lea edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (SevEsIsEnabled)] - cmp byte [edi], 1 ; SevEsIsEnabled - jne CProcedureInvoke - ; - ; program GHCB - ; Each page after the GHCB is a per-CPU page, so the calculation pro= grams - ; a GHCB to be every 8KB. + ; Setup the GHCB when AMD SEV-ES active. ; - mov eax, SIZE_4KB - shl eax, 1 ; EAX =3D SIZE_4K * 2 - mov ecx, ebx - mul ecx ; EAX =3D SIZE_4K * 2 * C= puNumber - mov edi, esi - add edi, MP_CPU_EXCHANGE_INFO_FIELD (GhcbBase) - add rax, qword [edi] - mov rdx, rax - shr rdx, 32 - mov rcx, 0xc0010130 - wrmsr + OneTimeCall SevEsSetupGhcb jmp CProcedureInvoke =20 GetApicId: - lea edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (SevEsIsEnabled)] - cmp byte [edi], 1 ; SevEsIsEnabled - jne DoCpuid - ; - ; Since we don't have a stack yet, we can't take a #VC - ; exception. Use the GHCB protocol to perform the CPUID - ; calls. + ; Use the GHCB protocol to get the ApicId when SEV-ES is active. ; - mov rcx, 0xc0010130 - rdmsr - shl rdx, 32 - or rax, rdx - mov rdi, rax ; RDI now holds the original GHCB GPA - - mov rdx, 0 ; CPUID function 0 - mov rax, 0 ; RAX register requested - or rax, 4 - wrmsr - rep vmmcall - rdmsr - cmp edx, 0bh - jb NoX2ApicSevEs ; CPUID level below CPUID_EXTENDED_TOP= OLOGY - - mov rdx, 0bh ; CPUID function 0x0b - mov rax, 040000000h ; RBX register requested - or rax, 4 - wrmsr - rep vmmcall - rdmsr - test edx, 0ffffh - jz NoX2ApicSevEs ; CPUID.0BH:EBX[15:0] is zero - - mov rdx, 0bh ; CPUID function 0x0b - mov rax, 0c0000000h ; RDX register requested - or rax, 4 - wrmsr - rep vmmcall - rdmsr - - ; Processor is x2APIC capable; 32-bit x2APIC ID is now in EDX - jmp RestoreGhcb - -NoX2ApicSevEs: - ; Processor is not x2APIC capable, so get 8-bit APIC ID - mov rdx, 1 ; CPUID function 1 - mov rax, 040000000h ; RBX register requested - or rax, 4 - wrmsr - rep vmmcall - rdmsr - shr edx, 24 - -RestoreGhcb: - mov rbx, rdx ; Save x2APIC/APIC ID - - mov rdx, rdi ; RDI holds the saved GHCB GPA - shr rdx, 32 - mov eax, edi - wrmsr - - mov rdx, rbx - - ; x2APIC ID or APIC ID is in EDX - jmp GetProcessorNumber + OneTimeCall SevEsGetApicId =20 DoCpuid: mov eax, 0 --=20 2.25.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#82362): https://edk2.groups.io/g/devel/message/82362 Mute This Topic: https://groups.io/mt/86448794/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-