From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM12-MW2-obe.outbound.protection.outlook.com (NAM12-MW2-obe.outbound.protection.outlook.com [40.107.244.76]) by mx.groups.io with SMTP id smtpd.web09.1336.1632163580550735194 for ; Mon, 20 Sep 2021 11:46:22 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="body hash did not verify" header.i=@amd.com header.s=selector1 header.b=iXwH8SEt; spf=permerror, err=parse error for token &{10 18 %{i}._ip.%{h}._ehlo.%{d}._spf.vali.email}: invalid domain name (domain: amd.com, ip: 40.107.244.76, mailfrom: brijesh.singh@amd.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=XzZp7mz2ZBT0eT3CsV5WGiE34piHHmu/DrlNgCkWFpCU/bAbMGZICA8eXsOZAp0klSt2nVCALVZHj24h7DJXyGvSmupHuHpk6BwXXmrLl5SD238cOZ9MQBnJdMTS8g5R/F9sv//VvE890Rfbe1aFiMCNxAk6IptFfGAh1JaXSEML3ojkab/jBtMckbSQJb5xAZ0xiWgqp65xmlPZF8J5tdI98WhKUEBjI8GImhNiJ2JGkvJv/iyW984JQYoa8a5u8j/9ddOQ1UF75FomIQxprABZPbowLS1/lw4ESe9jPy+GbC9fvydI9Gknm84ObZR5G9BpekgPNpHtS7WaI+cAvw== 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; bh=XFw81/VdnZTV6s8iSc/cTLsVp8a2N98OPbm3nTlTU98=; b=a/PGwGiod80OAno6HHBZe5znAb2LrcHSEWAaiIVWMaNqdxr3We2jKCQLCdrLNR+/lrO56364Z6MIv52ehT3L3TDIGPcTicvOBIrToEb3DC9AuNEY+eHzg3XncbXPDnMXvP5dGss2j4Nzc7xoid6PeKo+d4CQzFjjBEdYpHWYEi9T8OuV27GhWtFeLnXOwnCoruysKN+THy8wgfZzFFTfJDU6EL1T0qeBaevmTaKS3YpEu/dEpezBHiBTbh3qff3uZbhhKLoebw2/ESJ0M3wDkswGGHac+vSeOIsIN7ZmQcJrIc7uwOp3mjNwaaYTUOLJ9VWf7bVrR2GAEE3ITyRyhQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=amd.com; dmarc=pass action=none header.from=amd.com; dkim=pass header.d=amd.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=XFw81/VdnZTV6s8iSc/cTLsVp8a2N98OPbm3nTlTU98=; b=iXwH8SEtDJEBpKvOfQmI6Fhaqv7ocRtPIwGJGhOG6BqtnMftQMN0AflKTdiFpJRKEChOPhlW8K2BZnnqrnxo1a1te3NuhjRYMaiBzUD5XAwNcVYbU0f6HNwazTiBlwklmhRKRpCxo8eoExDXcuPrRJelqwSP2FWRrjZfLSHI4Js= Authentication-Results: edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=none action=none header.from=amd.com; Received: from SN6PR12MB2718.namprd12.prod.outlook.com (2603:10b6:805:6f::22) by SA0PR12MB4349.namprd12.prod.outlook.com (2603:10b6:806:98::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.14; Mon, 20 Sep 2021 18:46:20 +0000 Received: from SN6PR12MB2718.namprd12.prod.outlook.com ([fe80::78b7:7336:d363:9be3]) by SN6PR12MB2718.namprd12.prod.outlook.com ([fe80::78b7:7336:d363:9be3%6]) with mapi id 15.20.4523.018; Mon, 20 Sep 2021 18:46:20 +0000 From: "Brijesh Singh" To: devel@edk2.groups.io 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: [PATCH v8 02/32] UefiCpuPkg/MpInitLib: move SEV specific routines in AmdSev.c Date: Mon, 20 Sep 2021 13:45:34 -0500 Message-ID: <20210920184604.31590-3-brijesh.singh@amd.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210920184604.31590-1-brijesh.singh@amd.com> References: <20210920184604.31590-1-brijesh.singh@amd.com> X-ClientProxiedBy: SN4PR0201CA0034.namprd02.prod.outlook.com (2603:10b6:803:2e::20) To SN6PR12MB2718.namprd12.prod.outlook.com (2603:10b6:805:6f::22) Return-Path: brijesh.singh@amd.com MIME-Version: 1.0 Received: from sbrijesh-desktop.amd.com (165.204.77.1) by SN4PR0201CA0034.namprd02.prod.outlook.com (2603:10b6:803:2e::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4523.14 via Frontend Transport; Mon, 20 Sep 2021 18:46:19 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 13661c8d-ac5f-47e5-ad01-08d97c66efeb X-MS-TrafficTypeDiagnostic: SA0PR12MB4349: X-MS-Exchange-Transport-Forked: True 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: BCL:0; X-Microsoft-Antispam-Message-Info: C+S1436y3kMrseSegf+qfYrA3EaJMdS0n1DcKG3yEfY/rEaEXSb9Fb6SbM3kBulPSvYng126alUyThW1eVGCCm0f9WXgjDvLMgjjOdwxuBGTM+XSyZ8vADVDlk3ucdePJoyjk+1uUGCwa6ZPqO018tGZ6FSPF6MmfqO5jfOGIbJige4aAneM87n79LG+eWjjazI5qC6KUtC2kXpT7khnm0xqjNXJMwIgLTbaUatvXSAUKOv9xVCKrBsZoIKnqMEr0aMh2M9DixRTlTmX6Z3I7Zx1irVo+Gg5nFwq7Qm1z3Hb3LqsixbbOFdpzRMTn8rBWLD64CCLCBrPWDwca20Du++VyNu0XKmGytQ5D8zdmWvRYW1qvJ66Ixusfro3E+fB3P40I5ox23aHZ1SRLvHFIPS9FprEjAL4V9XtKlp+STOddUPx1YJ+p4ByCSYcYPUC4S3480XeuEdOIktyXzYn3FF2Rx49q6pjFyNK1R6oWFlfHo7GLnIBGJlSfFS/OC/xmiIVfVDXhG8pHBF5Ny/dLVs8Y+v9MBsrre2CZmoaxYa8njFJAqeOTYAu9gTf3fO2Dh7dixR6ilpadPR2kX4S4LiPPCCCEbxYdaVCamP4Vrpog1NTE32tetG++5eflXJUOmNz47JaWXgS7juvDleHjWjMWG2O8c6gJoVIx1Ge2CbcQ2szzjfPbEW/i+uW9qdVINd7nskUk0kHDEmnm9tH8p0SWwo2cKISJX/3o+RkR9s3RP1F1/trgdlgyyBkGLjUvg+7j6NpOXDJrVY/gipATvs5j5Qz3EXvJjjT891uv5A= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SN6PR12MB2718.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(6029001)(4636009)(366004)(44832011)(66476007)(36756003)(5660300002)(508600001)(38350700002)(6916009)(186003)(6666004)(66556008)(7696005)(2616005)(956004)(30864003)(66946007)(6486002)(52116002)(2906002)(4326008)(26005)(83380400001)(966005)(316002)(86362001)(8936002)(7416002)(19627235002)(54906003)(38100700002)(8676002)(1076003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?MayxTWYuQCM/y8LsLwrqZG8yzHE7CeOqcoEsRgO1QZR0RErMUSgtl99qrwPy?= =?us-ascii?Q?sT8KYi9Kp9+J7O6210sZbP62vXwN4R49tkIFb3ngw2ug2t6vr6HXR5OfZ+nx?= =?us-ascii?Q?lEBJAglPQldeQ6VRnAeeIwPns0VbcMwlfk1Rq/6DTXUeZAlMeeIEDhd/YwIK?= =?us-ascii?Q?6hJTT0LJwWOoHl1GqebfHvrAQJUWRsjEAuhceh0N9hZBu3ecP3eOMAWZgqQh?= =?us-ascii?Q?HCbrTMj/VGUhbqzclAIVcKdXSIZdSuy/4m2cM8uvbc5u5t9Hm3I7RuOQoxW9?= =?us-ascii?Q?p6tFrJuhLBg4Y6ebB3wFKV/Piks0SJJKasnU4DJqo0bEZ3IAmAIUAhwxa5Sb?= =?us-ascii?Q?+KdOhgNvZdI5Ss9efDr8bwFnlHkBFiLwN4LvJfEMJgUuzbzo4NIp8eGZKjKE?= =?us-ascii?Q?iWn7sX4KvEVvf3qW00CtIbnwFX74Ndsr1K1/IVYlQg+oSLF+bFMWqfThYI0b?= =?us-ascii?Q?UKBN73+xdi5jrDqDVRESWAjsx8OXyZvw0r373h2CymBGWLb5+M2s4FTacH9k?= =?us-ascii?Q?239DhL43Yd1xgQAA7sAx/yXX00er+n8tWoIHUIXzmehWFVKocoa3SrW486GB?= =?us-ascii?Q?jgaT7izEa1I5wshBRQtAtvyzDrF01cCZa5J5F388q9SQ+XlO+o1BOwRhf95v?= =?us-ascii?Q?bwBKYxfRRg6p8665qs8PmwDmJHXdzkj2nF0VccCcS1WCmUogS991ZIn6ErEs?= =?us-ascii?Q?vgBXvaZPBPrR+tbLCi2JfLIsMxRVqlidDUuB0bmr/9HxLU9A2HcnTpu1QIsa?= =?us-ascii?Q?oLz10CcqjLcEgxO9i0dQzhbW+HPdjrK0V4tsvmRk7olX7Yr91WbfvmiMPTe9?= =?us-ascii?Q?pPjFD8FlXNhzDRvw/Xx6Ow4q9qU6f0Vlw8r7jw6OzCtzsb30zvf6P5ise4fO?= =?us-ascii?Q?au1EkteFI/DI/GSGQ0O9cBMRoZz4E0GwkRdGHn13cybOkTxmvRiA0uITMWlV?= =?us-ascii?Q?Ct5pkDQG6VrZHzPeTHQsYZcqdr/vZuhAcDq/15sqY4/Tywp12VkR5AdaL6vv?= =?us-ascii?Q?qyOcVv0GNsb6rie9QaOKNzN6Llxwyj2FSi589FW2R0Hve2LauCTD+V9QEfpK?= =?us-ascii?Q?kzO5yL63nvY0SoNwZyQrkJOdstJ6uTW2lih8h0j9fGg8SfGJd1n0RzCbHP9y?= =?us-ascii?Q?OSofErBNbkErzJUPzRnueOHV0VRmTFLvcYmaTN0kFh0nPxxon49DibsJ4nOE?= =?us-ascii?Q?YHIrvqMQvkuN3dwJT7g9rgSEmLLn3vOGIisGE/r0k2TYsMJ73633t/ZsrCt2?= =?us-ascii?Q?8gVwEddtHoCfkL0PCE+5h8bwLGF0bhQ6gvZM82+KzIN/Imot8bb8gTXZAZWp?= =?us-ascii?Q?eLdTqCEDzIAt7khMXkXOcf6d?= X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-Network-Message-Id: 13661c8d-ac5f-47e5-ad01-08d97c66efeb X-MS-Exchange-CrossTenant-AuthSource: SN6PR12MB2718.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Sep 2021 18:46:20.5622 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: wBLhJPagandQ9IcFbv2sV+eaaLzCh4dXb5FUr8AtlP5prD0rUQ0ZGamw19x9aYjRmHinEuEezWTmEbpfHFYsWw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA0PR12MB4349 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain 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 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