From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM11-DM6-obe.outbound.protection.outlook.com (NAM11-DM6-obe.outbound.protection.outlook.com [40.107.223.73]) by mx.groups.io with SMTP id smtpd.web09.6951.1639020576163630543 for ; Wed, 08 Dec 2021 19:29:36 -0800 Authentication-Results: mx.groups.io; dkim=fail reason="body hash did not verify" header.i=@amd.com header.s=selector1 header.b=NmYA1UBN; 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.223.73, mailfrom: brijesh.singh@amd.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=W+cSUO1tqbO0yN2m6DuBjw6M/0FSrB7M7gAnJ6Ikh29coLlzLCLqn7FjL0zIKtAFyTDrQSgSyY30C4kkOBWP04LnC18ReWsjx8AGbLj50U2ubzQW/SbnO3/YPKYrZNwtpOexujzG9TVHHun0vFNRh2+ZMZtZJzPvc1IhVXEkZBwwaevjUft2md/a1gpfZpDhjsmxJRhca91AUrbesJThx8sdrB9OWjjHGedkfbZzLYdzt7tJUINbxyPpRDRE871TvPMCD32ATeL0HJzCOHlnHW+kQEV0NtMhJXl/7yaikL7MVHm9jkUgOVYmwlmKS/n/r60EnMTp5oNtkWULyVEU/w== 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=S+iW/Y+gMuUwcZnEtxgG9B6KQ+dEJ2kCma8+RjqdC38=; b=OGL6oDhUa6jcRTArG04MGLb7qLmwrzQSyvy4EG78ZyzpJT+f6snZJXl4cJCYc4jJlMHjKMHzlZG7E7S1XRlUN+03xIMJ4eBU05ndtSjrFQ79ikr+pW59cqB7tW4n9EMFe6kFdIm4FaoeZtRZlxZFy3m1sCN42a4ncJBLJ4lIrwiTadF61g5lv222xcFQ1GaeUfMVjscI3M1Nws0j9Nw9ca8JIYlJZq+cNDqnFe9hvBQiTMqd9msUWf9V4pyez3LEcO9w3sGarkvCSDK/n4bptxaR7Vo67otEzCQzgiKFYJCPgGUDq/GC/kh+EyxkEMENgOSvOULZrFemzap19MMKNg== 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 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=S+iW/Y+gMuUwcZnEtxgG9B6KQ+dEJ2kCma8+RjqdC38=; b=NmYA1UBNa0s3yk+j/DrY1EpZC1LfIF71cVLp75N5bvQg6BmnNr/XYeW2BnVpakBz6bQCBE7/SuFRHfdGhUpF00z9hCrXNTZr1/YyNudIZmm2OJKZG9vTsdiGo5RolsXwHB4OtV/QrkpOcldldGvEzQbyKaewx+1pzmPUsaGuWO0= Received: from MWHPR14CA0001.namprd14.prod.outlook.com (2603:10b6:300:ae::11) by MN2PR12MB4814.namprd12.prod.outlook.com (2603:10b6:208:1b6::32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4734.24; Thu, 9 Dec 2021 03:29:28 +0000 Received: from CO1NAM11FT041.eop-nam11.prod.protection.outlook.com (2603:10b6:300:ae:cafe::aa) by MWHPR14CA0001.outlook.office365.com (2603:10b6:300:ae::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4755.20 via Frontend Transport; Thu, 9 Dec 2021 03:29:28 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; 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=SATLEXMB03.amd.com; Received: from SATLEXMB03.amd.com (165.204.84.17) by CO1NAM11FT041.mail.protection.outlook.com (10.13.174.217) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.4755.13 via Frontend Transport; Thu, 9 Dec 2021 03:29:27 +0000 Received: from sbrijesh-desktop.amd.com (10.180.168.240) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.17; Wed, 8 Dec 2021 21:29:25 -0600 From: "Brijesh Singh" To: CC: James Bottomley , Min Xu , "Jiewen Yao" , Tom Lendacky , "Jordan Justen" , Ard Biesheuvel , Erdem Aktas , "Michael Roth" , Gerd Hoffmann , "Michael D Kinney" , Liming Gao , Zhiguang Liu , Ray Ni , Rahul Kumar , Eric Dong , Michael Roth , Brijesh Singh Subject: [PATCH v14 32/32] UefiCpuPkg/MpInitLib: Use SEV-SNP AP Creation NAE event to launch APs Date: Wed, 8 Dec 2021 21:28:00 -0600 Message-ID: <20211209032800.3802995-33-brijesh.singh@amd.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211209032800.3802995-1-brijesh.singh@amd.com> References: <20211209032800.3802995-1-brijesh.singh@amd.com> MIME-Version: 1.0 Return-Path: brijesh.singh@amd.com X-Originating-IP: [10.180.168.240] X-ClientProxiedBy: SATLEXMB03.amd.com (10.181.40.144) To SATLEXMB03.amd.com (10.181.40.144) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: c7b062cc-8f01-4bf6-4f71-08d9bac41b06 X-MS-TrafficTypeDiagnostic: MN2PR12MB4814:EE_ X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:10000; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: CUn+OP7Q9K/QwvdyQIJtbeGcm2E/r3hP6Wsr2OQeLy6lSgMiviBCDOk3px2/BfY0VZ3Gol0Ov9/805j5bzlkG5ImbMnvRaLT/SjUwaNxcM0zS+oZCw1FmlJgzJH8YFpPVTs7foUF0k1JB+gyltJ39pi+fvCXOJEzu3Xez4gwEvnfEyRCnbhYv6St9fNOLMhUhpCl5Q9nDMGAb4eKc5nE0J25cT7DTk40NudPRN6IQXDk3BvhorwQaF/V/6GHSstTlO82V19AW8Ieti02xRBUY2TIrc6mPVyXUCkaPsrPSBvNX8DNoshBKr75OMSexOggXVMGzWY6v7vXi7fFk7fAwd3J0ElXynuk4rn5h2nn3QPu3KDyJGxHjB4uqX1zntuQXUPWzuwIt/l8PUprvz0wgf3a3IpYjNd1mymvbAuZwh954h50qNAyGHFNwXu6ZWyyB2720UI6dgYSzWvzzK1FHa6ssDKREWX1q5vr42QXF1fSQ6eNSlUqECUPeyk48OOzgvb/BrQlWoY2iRUEkKMUdUCq1V0fQBMIEDBK7pfpREXhi3R0J/IOrQhO9BKK+aN4CqT31ez+8ysHPUBR4qJ6NcmWRknzCsrcv1KB6eV1lkPbzQnloXcw8659VRDXzFt0kaujKxRWvcJ3T2tUIgqiiGI1V+NOx+sRRXpaJeUFrF5g0rF0tvYrC8A9c9HS1mddLXdJmadJXzjCbH9ztd4QvvXjE1NhTe9qHlyR6dHVZoGVc/Avod+ONZu349Y/MpRSQbdZe818k8l/FxO+eIqSbJiujQZNeB+y+A3bS5QNrjAYkp71C1w9zIysJr7VNDuUrYx/9iMN6YRUKyRo9xrpMgtzb9u8/L7QNaANUNUEWb9pgV8OTxPanjQQPbx+ydjf X-Forefront-Antispam-Report: CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:CAL;SFV:NSPM;H:SATLEXMB03.amd.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(6029001)(4636009)(46966006)(36840700001)(40470700001)(508600001)(966005)(70586007)(6916009)(19627235002)(36756003)(70206006)(81166007)(30864003)(8936002)(426003)(7696005)(2616005)(7416002)(83380400001)(4326008)(186003)(54906003)(356005)(44832011)(82310400004)(316002)(16526019)(86362001)(1076003)(26005)(36860700001)(40460700001)(5660300002)(6666004)(336012)(47076005)(8676002)(2906002)(36900700001);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Dec 2021 03:29:27.7671 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: c7b062cc-8f01-4bf6-4f71-08d9bac41b06 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=[SATLEXMB03.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CO1NAM11FT041.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB4814 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain From: Tom Lendacky BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3275 Use the SEV-SNP AP Creation NAE event to create and launch APs under SEV-SNP. This capability will be advertised in the SEV Hypervisor Feature Support PCD (PcdSevEsHypervisorFeatures). Cc: Michael Roth Cc: Eric Dong Cc: Ray Ni Cc: Rahul Kumar 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: Ray Ni Acked-by: Gerd Hoffmann Signed-off-by: Tom Lendacky Signed-off-by: Brijesh Singh --- UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf | 3 + UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf | 3 + UefiCpuPkg/Library/MpInitLib/MpLib.h | 44 +++ UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 13 +- UefiCpuPkg/Library/MpInitLib/Ia32/AmdSev.c | 70 +++++ UefiCpuPkg/Library/MpInitLib/MpLib.c | 59 ++-- UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c | 263 ++++++++++++++++++ 7 files changed, 433 insertions(+), 22 deletions(-) create mode 100644 UefiCpuPkg/Library/MpInitLib/Ia32/AmdSev.c create mode 100644 UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf b/UefiCpuPkg/Lib= rary/MpInitLib/DxeMpInitLib.inf index de705bc54bb4..e1cd0b350008 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf @@ -22,9 +22,11 @@ [Defines] # =20 [Sources.IA32] + Ia32/AmdSev.c Ia32/MpFuncs.nasm =20 [Sources.X64] + X64/AmdSev.c X64/MpFuncs.nasm =20 [Sources.common] @@ -73,6 +75,7 @@ [Pcd] gUefiCpuPkgTokenSpaceGuid.PcdCpuApLoopMode ## = CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuApTargetCstate ## = SOMETIMES_CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdCpuApStatusCheckIntervalInMicroSeconds ## = CONSUMES + gUefiCpuPkgTokenSpaceGuid.PcdGhcbHypervisorFeatures ## = CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase ## = SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## = CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## = CONSUMES diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf b/UefiCpuPkg/Lib= rary/MpInitLib/PeiMpInitLib.inf index b7e15ee023f0..5facf4db9499 100644 --- a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf +++ b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf @@ -22,9 +22,11 @@ [Defines] # =20 [Sources.IA32] + Ia32/AmdSev.c Ia32/MpFuncs.nasm =20 [Sources.X64] + X64/AmdSev.c X64/MpFuncs.nasm =20 [Sources.common] @@ -64,6 +66,7 @@ [Pcd] gUefiCpuPkgTokenSpaceGuid.PcdCpuApLoopMode ## CONS= UMES gUefiCpuPkgTokenSpaceGuid.PcdCpuApTargetCstate ## SOME= TIMES_CONSUMES gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase ## SOME= TIMES_CONSUMES + gUefiCpuPkgTokenSpaceGuid.PcdGhcbHypervisorFeatures ## CONS= UMES gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONS= UMES gEfiMdePkgTokenSpaceGuid.PcdConfidentialComputingGuestAttr ## CONS= UMES =20 diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpIn= itLib/MpLib.h index be67cd88ec46..7d84a56fbc51 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -15,6 +15,7 @@ =20 #include #include +#include #include #include #include @@ -150,6 +151,7 @@ typedef struct { UINT8 PlatformId; UINT64 MicrocodeEntryAddr; UINT32 MicrocodeRevision; + SEV_ES_SAVE_AREA *SevEsSaveArea; } CPU_AP_DATA; =20 // @@ -294,6 +296,7 @@ struct _CPU_MP_DATA { =20 BOOLEAN SevEsIsEnabled; BOOLEAN SevSnpIsEnabled; + BOOLEAN UseSevEsAPMethod; UINTN SevEsAPBuffer; UINTN SevEsAPResetStackStart; CPU_MP_DATA *NewCpuMpData; @@ -799,4 +802,45 @@ FillExchangeInfoDataSevEs ( IN volatile MP_CPU_EXCHANGE_INFO *ExchangeInfo ); =20 +/** + Issue RMPADJUST to adjust the VMSA attribute of an SEV-SNP page. + + @param[in] PageAddress + @param[in] VmsaPage + + @return RMPADJUST return value +**/ +UINT32 +SevSnpRmpAdjust ( + IN EFI_PHYSICAL_ADDRESS PageAddress, + IN BOOLEAN VmsaPage + ); + +/** + Create an SEV-SNP AP save area (VMSA) for use in running the vCPU. + + @param[in] CpuMpData Pointer to CPU MP Data + @param[in] CpuData Pointer to CPU AP Data + @param[in] ApicId APIC ID of the vCPU +**/ +VOID +SevSnpCreateSaveArea ( + IN CPU_MP_DATA *CpuMpData, + IN CPU_AP_DATA *CpuData, + UINT32 ApicId + ); + +/** + Create SEV-SNP APs. + + @param[in] CpuMpData Pointer to CPU MP Data + @param[in] ProcessorNumber The handle number of specified processor + (-1 for all APs) +**/ +VOID +SevSnpCreateAP ( + IN CPU_MP_DATA *CpuMpData, + IN INTN ProcessorNumber + ); + #endif diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/M= pInitLib/DxeMpLib.c index 02bc9c2bd2c4..60d14a5a0e10 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c @@ -93,7 +93,14 @@ GetWakeupBuffer ( EFI_PHYSICAL_ADDRESS StartAddress; EFI_MEMORY_TYPE MemoryType; =20 - if (ConfidentialComputingGuestHas (CCAttrAmdSevEs)) { + if (ConfidentialComputingGuestHas (CCAttrAmdSevEs) && + !ConfidentialComputingGuestHas (CCAttrAmdSevSnp)) + { + // + // An SEV-ES-only guest requires the memory to be reserved. SEV-SNP, w= hich + // is also considered SEV-ES, uses a different AP startup method, thou= gh, + // which does not have the same requirement. + // MemoryType =3D EfiReservedMemoryType; } else { MemoryType =3D EfiBootServicesData; @@ -380,7 +387,7 @@ RelocateApLoop ( MpInitLibWhoAmI (&ProcessorNumber); CpuMpData =3D GetCpuMpData (); MwaitSupport =3D IsMwaitSupport (); - if (CpuMpData->SevEsIsEnabled) { + if (CpuMpData->UseSevEsAPMethod) { StackStart =3D CpuMpData->SevEsAPResetStackStart; } else { StackStart =3D mReservedTopOfApStack; @@ -430,7 +437,7 @@ MpInitChangeApLoopCallback ( CpuPause (); } =20 - if (CpuMpData->SevEsIsEnabled && (CpuMpData->WakeupBuffer !=3D (UINTN)-1= )) { + if (CpuMpData->UseSevEsAPMethod && (CpuMpData->WakeupBuffer !=3D (UINTN)= -1)) { // // There are APs present. Re-use reserved memory area below 1MB from // WakeupBuffer as the area to be used for transitioning to 16-bit mod= e diff --git a/UefiCpuPkg/Library/MpInitLib/Ia32/AmdSev.c b/UefiCpuPkg/Librar= y/MpInitLib/Ia32/AmdSev.c new file mode 100644 index 000000000000..c83144285b68 --- /dev/null +++ b/UefiCpuPkg/Library/MpInitLib/Ia32/AmdSev.c @@ -0,0 +1,70 @@ +/** @file + + AMD SEV helper function. + + Copyright (c) 2021, AMD Incorporated. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MpLib.h" + +/** + Create an SEV-SNP AP save area (VMSA) for use in running the vCPU. + + @param[in] CpuMpData Pointer to CPU MP Data + @param[in] CpuData Pointer to CPU AP Data + @param[in] ApicId APIC ID of the vCPU +**/ +VOID +SevSnpCreateSaveArea ( + IN CPU_MP_DATA *CpuMpData, + IN CPU_AP_DATA *CpuData, + UINT32 ApicId + ) +{ + // + // SEV-SNP is not support on 32-bit build. + // + ASSERT (FALSE); +} + +/** + Create SEV-SNP APs. + + @param[in] CpuMpData Pointer to CPU MP Data + @param[in] ProcessorNumber The handle number of specified processor + (-1 for all APs) +**/ +VOID +SevSnpCreateAP ( + IN CPU_MP_DATA *CpuMpData, + IN INTN ProcessorNumber + ) +{ + // + // SEV-SNP is not support on 32-bit build. + // + ASSERT (FALSE); +} + +/** + Issue RMPADJUST to adjust the VMSA attribute of an SEV-SNP page. + + @param[in] PageAddress + @param[in] VmsaPage + + @return RMPADJUST return value +**/ +UINT32 +SevSnpRmpAdjust ( + IN EFI_PHYSICAL_ADDRESS PageAddress, + IN BOOLEAN VmsaPage + ) +{ + // + // RMPADJUST is not supported in 32-bit mode + // + return RETURN_UNSUPPORTED; +} diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpIn= itLib/MpLib.c index b73a6e9a0ffc..4a73787ee43a 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -295,10 +295,12 @@ GetApLoopMode ( ApLoopMode =3D ApInHltLoop; } =20 - if (ConfidentialComputingGuestHas (CCAttrAmdSevEs)) { + if (ConfidentialComputingGuestHas (CCAttrAmdSevEs) && + !ConfidentialComputingGuestHas (CCAttrAmdSevSnp)) + { // - // For SEV-ES, force AP in Hlt-loop mode in order to use the GHCB - // protocol for starting APs + // For SEV-ES (SEV-SNP is also considered SEV-ES), force AP in Hlt-l= oop + // mode in order to use the GHCB protocol for starting APs // ApLoopMode =3D ApInHltLoop; } @@ -763,7 +765,7 @@ ApWakeupFunction ( // to allow the APs to issue an AP_RESET_HOLD before the BSP possibl= y // performs another INIT-SIPI-SIPI sequence. // - if (!CpuMpData->SevEsIsEnabled) { + if (!CpuMpData->UseSevEsAPMethod) { InterlockedDecrement ((UINT32 *)&CpuMpData->MpCpuExchangeInfo->Num= ApsExecuting); } } @@ -777,7 +779,7 @@ ApWakeupFunction ( // while (TRUE) { DisableInterrupts (); - if (CpuMpData->SevEsIsEnabled) { + if (CpuMpData->UseSevEsAPMethod) { SevEsPlaceApHlt (CpuMpData); } else { CpuSleep (); @@ -1061,9 +1063,13 @@ AllocateResetVector ( ); // // The AP reset stack is only used by SEV-ES guests. Do not allocate i= t - // if SEV-ES is not enabled. + // if SEV-ES is not enabled. An SEV-SNP guest is also considered + // an SEV-ES guest, but uses a different method of AP startup, elimina= ting + // the need for the allocation. // - if (ConfidentialComputingGuestHas (CCAttrAmdSevEs)) { + if (ConfidentialComputingGuestHas (CCAttrAmdSevEs) && + !ConfidentialComputingGuestHas (CCAttrAmdSevSnp)) + { // // Stack location is based on ProcessorNumber, so use the total numb= er // of processors for calculating the total stack area. @@ -1114,7 +1120,7 @@ FreeResetVector ( // perform the restore as this will overwrite memory which has data // needed by SEV-ES. // - if (!CpuMpData->SevEsIsEnabled) { + if (!CpuMpData->UseSevEsAPMethod) { RestoreWakeupBuffer (CpuMpData); } } @@ -1193,7 +1199,7 @@ WakeUpAP ( =20 if (ResetVectorRequired) { // - // For SEV-ES, the initial AP boot address will be defined by + // For SEV-ES and SEV-SNP, the initial AP boot address will be defin= ed by // PcdSevEsWorkAreaBase. The Segment/Rip must be the jump address // from the original INIT-SIPI-SIPI. // @@ -1203,8 +1209,14 @@ WakeUpAP ( =20 // // Wakeup all APs + // Must use the INIT-SIPI-SIPI method for initial configuration in + // order to obtain the APIC ID. // - SendInitSipiSipiAllExcludingSelf ((UINT32)ExchangeInfo->BufferStart)= ; + if (CpuMpData->SevSnpIsEnabled && (CpuMpData->InitFlag !=3D ApInitCo= nfig)) { + SevSnpCreateAP (CpuMpData, -1); + } else { + SendInitSipiSipiAllExcludingSelf ((UINT32)ExchangeInfo->BufferStar= t); + } } =20 if (CpuMpData->InitFlag =3D=3D ApInitConfig) { @@ -1295,7 +1307,7 @@ WakeUpAP ( CpuInfoInHob =3D (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob; =20 // - // For SEV-ES, the initial AP boot address will be defined by + // For SEV-ES and SEV-SNP, the initial AP boot address will be defin= ed by // PcdSevEsWorkAreaBase. The Segment/Rip must be the jump address // from the original INIT-SIPI-SIPI. // @@ -1303,10 +1315,14 @@ WakeUpAP ( SetSevEsJumpTable (ExchangeInfo->BufferStart); } =20 - SendInitSipiSipi ( - CpuInfoInHob[ProcessorNumber].ApicId, - (UINT32)ExchangeInfo->BufferStart - ); + if (CpuMpData->SevSnpIsEnabled && (CpuMpData->InitFlag !=3D ApInitCo= nfig)) { + SevSnpCreateAP (CpuMpData, (INTN)ProcessorNumber); + } else { + SendInitSipiSipi ( + CpuInfoInHob[ProcessorNumber].ApicId, + (UINT32)ExchangeInfo->BufferStart + ); + } } =20 // @@ -1855,10 +1871,15 @@ MpInitLibInitialize ( CpuMpData->CpuData =3D (CPU_AP_DATA *)(CpuMpData + 1); CpuMpData->CpuInfoInHob =3D (UINT64)(UINTN)(CpuMpData->CpuData + Max= LogicalProcessorNumber); InitializeSpinLock (&CpuMpData->MpLock); - CpuMpData->SevEsIsEnabled =3D ConfidentialComputingGuestHas (CCAttrAmdS= evEs); - CpuMpData->SevSnpIsEnabled =3D ConfidentialComputingGuestHas (CCAttrAmdS= evSnp); - CpuMpData->SevEsAPBuffer =3D (UINTN)-1; - CpuMpData->GhcbBase =3D PcdGet64 (PcdGhcbBase); + CpuMpData->SevEsIsEnabled =3D ConfidentialComputingGuestHas (CCAttrAmd= SevEs); + CpuMpData->SevSnpIsEnabled =3D ConfidentialComputingGuestHas (CCAttrAmd= SevSnp); + CpuMpData->SevEsAPBuffer =3D (UINTN)-1; + CpuMpData->GhcbBase =3D PcdGet64 (PcdGhcbBase); + CpuMpData->UseSevEsAPMethod =3D CpuMpData->SevEsIsEnabled && !CpuMpData-= >SevSnpIsEnabled; + + if (CpuMpData->SevSnpIsEnabled) { + ASSERT ((PcdGet64 (PcdGhcbHypervisorFeatures) & GHCB_HV_FEATURES_SNP_A= P_CREATE) =3D=3D GHCB_HV_FEATURES_SNP_AP_CREATE); + } =20 // // Make sure no memory usage outside of the allocated buffer. diff --git a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c b/UefiCpuPkg/Library= /MpInitLib/X64/AmdSev.c new file mode 100644 index 000000000000..a3cd377ef600 --- /dev/null +++ b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c @@ -0,0 +1,263 @@ +/** @file + + AMD SEV helper function. + + Copyright (c) 2021, AMD Incorporated. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MpLib.h" +#include +#include +#include + +/** + Create an SEV-SNP AP save area (VMSA) for use in running the vCPU. + + @param[in] CpuMpData Pointer to CPU MP Data + @param[in] CpuData Pointer to CPU AP Data + @param[in] ApicId APIC ID of the vCPU +**/ +VOID +SevSnpCreateSaveArea ( + IN CPU_MP_DATA *CpuMpData, + IN CPU_AP_DATA *CpuData, + UINT32 ApicId + ) +{ + SEV_ES_SAVE_AREA *SaveArea; + IA32_CR0 ApCr0; + IA32_CR0 ResetCr0; + IA32_CR4 ApCr4; + IA32_CR4 ResetCr4; + UINTN StartIp; + UINT8 SipiVector; + UINT32 RmpAdjustStatus; + UINT64 VmgExitStatus; + MSR_SEV_ES_GHCB_REGISTER Msr; + GHCB *Ghcb; + BOOLEAN InterruptState; + UINT64 ExitInfo1; + UINT64 ExitInfo2; + + // + // Allocate a single page for the SEV-ES Save Area and initialize it. + // + SaveArea =3D AllocateReservedPages (1); + if (!SaveArea) { + return; + } + + ZeroMem (SaveArea, EFI_PAGE_SIZE); + + // + // Propogate the CR0.NW and CR0.CD setting to the AP + // + ResetCr0.UintN =3D 0x00000010; + ApCr0.UintN =3D CpuData->VolatileRegisters.Cr0; + if (ApCr0.Bits.NW) { + ResetCr0.Bits.NW =3D 1; + } + + if (ApCr0.Bits.CD) { + ResetCr0.Bits.CD =3D 1; + } + + // + // Propagate the CR4.MCE setting to the AP + // + ResetCr4.UintN =3D 0; + ApCr4.UintN =3D CpuData->VolatileRegisters.Cr4; + if (ApCr4.Bits.MCE) { + ResetCr4.Bits.MCE =3D 1; + } + + // + // Convert the start IP into a SIPI Vector + // + StartIp =3D CpuMpData->MpCpuExchangeInfo->BufferStart; + SipiVector =3D (UINT8)(StartIp >> 12); + + // + // Set the CS:RIP value based on the start IP + // + SaveArea->Cs.Base =3D SipiVector << 12; + SaveArea->Cs.Selector =3D SipiVector << 8; + SaveArea->Cs.Limit =3D 0xFFFF; + SaveArea->Cs.Attributes.Bits.Present =3D 1; + SaveArea->Cs.Attributes.Bits.Sbit =3D 1; + SaveArea->Cs.Attributes.Bits.Type =3D SEV_ES_RESET_CODE_SEGMENT_TYPE; + SaveArea->Rip =3D StartIp & 0xFFF; + + // + // Set the remaining values as defined in APM for INIT + // + SaveArea->Ds.Limit =3D 0xFFFF; + SaveArea->Ds.Attributes.Bits.Present =3D 1; + SaveArea->Ds.Attributes.Bits.Sbit =3D 1; + SaveArea->Ds.Attributes.Bits.Type =3D SEV_ES_RESET_DATA_SEGMENT_TYPE; + SaveArea->Es =3D SaveArea->Ds; + SaveArea->Fs =3D SaveArea->Ds; + SaveArea->Gs =3D SaveArea->Ds; + SaveArea->Ss =3D SaveArea->Ds; + + SaveArea->Gdtr.Limit =3D 0xFFFF; + SaveArea->Ldtr.Limit =3D 0xFFFF; + SaveArea->Ldtr.Attributes.Bits.Present =3D 1; + SaveArea->Ldtr.Attributes.Bits.Type =3D SEV_ES_RESET_LDT_TYPE; + SaveArea->Idtr.Limit =3D 0xFFFF; + SaveArea->Tr.Limit =3D 0xFFFF; + SaveArea->Ldtr.Attributes.Bits.Present =3D 1; + SaveArea->Ldtr.Attributes.Bits.Type =3D SEV_ES_RESET_TSS_TYPE; + + SaveArea->Efer =3D 0x1000; + SaveArea->Cr4 =3D ResetCr4.UintN; + SaveArea->Cr0 =3D ResetCr0.UintN; + SaveArea->Dr7 =3D 0x0400; + SaveArea->Dr6 =3D 0xFFFF0FF0; + SaveArea->Rflags =3D 0x0002; + SaveArea->GPat =3D 0x0007040600070406ULL; + SaveArea->XCr0 =3D 0x0001; + SaveArea->Mxcsr =3D 0x1F80; + SaveArea->X87Ftw =3D 0x5555; + SaveArea->X87Fcw =3D 0x0040; + + // + // Set the SEV-SNP specific fields for the save area: + // VMPL - always VMPL0 + // SEV_FEATURES - equivalent to the SEV_STATUS MSR right shifted 2 bit= s + // + SaveArea->Vmpl =3D 0; + SaveArea->SevFeatures =3D AsmReadMsr64 (MSR_SEV_STATUS) >> 2; + + // + // To turn the page into a recognized VMSA page, issue RMPADJUST: + // Target VMPL but numerically higher than current VMPL + // Target PermissionMask is not used + // + RmpAdjustStatus =3D SevSnpRmpAdjust ( + (EFI_PHYSICAL_ADDRESS)(UINTN)SaveArea, + TRUE + ); + ASSERT (RmpAdjustStatus =3D=3D 0); + + ExitInfo1 =3D (UINT64)ApicId << 32; + ExitInfo1 |=3D SVM_VMGEXIT_SNP_AP_CREATE; + ExitInfo2 =3D (UINT64)(UINTN)SaveArea; + + Msr.GhcbPhysicalAddress =3D AsmReadMsr64 (MSR_SEV_ES_GHCB); + Ghcb =3D Msr.Ghcb; + + VmgInit (Ghcb, &InterruptState); + Ghcb->SaveArea.Rax =3D SaveArea->SevFeatures; + VmgSetOffsetValid (Ghcb, GhcbRax); + VmgExitStatus =3D VmgExit ( + Ghcb, + SVM_EXIT_SNP_AP_CREATION, + ExitInfo1, + ExitInfo2 + ); + VmgDone (Ghcb, InterruptState); + + ASSERT (VmgExitStatus =3D=3D 0); + if (VmgExitStatus !=3D 0) { + RmpAdjustStatus =3D SevSnpRmpAdjust ( + (EFI_PHYSICAL_ADDRESS)(UINTN)SaveArea, + FALSE + ); + if (RmpAdjustStatus =3D=3D 0) { + FreePages (SaveArea, 1); + } else { + DEBUG ((DEBUG_INFO, "SEV-SNP: RMPADJUST failed, leaking VMSA page\n"= )); + } + + SaveArea =3D NULL; + } + + if (CpuData->SevEsSaveArea) { + RmpAdjustStatus =3D SevSnpRmpAdjust ( + (EFI_PHYSICAL_ADDRESS)(UINTN)CpuData->SevEsSaveAre= a, + FALSE + ); + if (RmpAdjustStatus =3D=3D 0) { + FreePages (CpuData->SevEsSaveArea, 1); + } else { + DEBUG ((DEBUG_INFO, "SEV-SNP: RMPADJUST failed, leaking VMSA page\n"= )); + } + } + + CpuData->SevEsSaveArea =3D SaveArea; +} + +/** + Create SEV-SNP APs. + + @param[in] CpuMpData Pointer to CPU MP Data + @param[in] ProcessorNumber The handle number of specified processor + (-1 for all APs) +**/ +VOID +SevSnpCreateAP ( + IN CPU_MP_DATA *CpuMpData, + IN INTN ProcessorNumber + ) +{ + CPU_INFO_IN_HOB *CpuInfoInHob; + CPU_AP_DATA *CpuData; + UINTN Index; + UINT32 ApicId; + + ASSERT (CpuMpData->MpCpuExchangeInfo->BufferStart < 0x100000); + + CpuInfoInHob =3D (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob; + + if (ProcessorNumber < 0) { + for (Index =3D 0; Index < CpuMpData->CpuCount; Index++) { + if (Index !=3D CpuMpData->BspNumber) { + CpuData =3D &CpuMpData->CpuData[Index]; + ApicId =3D CpuInfoInHob[Index].ApicId, + SevSnpCreateSaveArea (CpuMpData, CpuData, ApicId); + } + } + } else { + Index =3D (UINTN)ProcessorNumber; + CpuData =3D &CpuMpData->CpuData[Index]; + ApicId =3D CpuInfoInHob[ProcessorNumber].ApicId, + SevSnpCreateSaveArea (CpuMpData, CpuData, ApicId); + } +} + +/** + Issue RMPADJUST to adjust the VMSA attribute of an SEV-SNP page. + + @param[in] PageAddress + @param[in] VmsaPage + + @return RMPADJUST return value +**/ +UINT32 +SevSnpRmpAdjust ( + IN EFI_PHYSICAL_ADDRESS PageAddress, + IN BOOLEAN VmsaPage + ) +{ + UINT64 Rdx; + + // + // The RMPADJUST instruction is used to set or clear the VMSA bit for a + // page. The VMSA change is only made when running at VMPL0 and is ignor= ed + // otherwise. If too low a target VMPL is specified, the instruction can + // succeed without changing the VMSA bit when not running at VMPL0. Usin= g a + // target VMPL level of 1, RMPADJUST will return a FAIL_PERMISSION error= if + // not running at VMPL0, thus ensuring that the VMSA bit is set appropri= ately + // when no error is returned. + // + Rdx =3D 1; + if (VmsaPage) { + Rdx |=3D RMPADJUST_VMSA_PAGE_BIT; + } + + return AsmRmpAdjust ((UINT64)PageAddress, 0, Rdx); +} --=20 2.25.1