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.web11.2921.1608065569831172631 for ; Tue, 15 Dec 2020 12:52:50 -0800 Authentication-Results: mx.groups.io; dkim=fail reason="body hash did not verify" header.i=@amdcloud.onmicrosoft.com header.s=selector2-amdcloud-onmicrosoft-com header.b=C5JENQYq; 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: thomas.lendacky@amd.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=mSUCVEsggoXlDTtMAKMRUZlln3Xhehtj10jCVy1bHBSel/kns7RkQz/ylKinIK6GmUhWc7eHg+Fp7TBb2Lw2NgyjTgMtJjBd8SxdLisodH1fMH1M7TEJYXW0XP3+QiAG7l1RI3JtVix0SdBUODQoB2SKQcvNiroiLRNN4wnOPmBZUhFa61UQKY5y9fR/pjGXKFS23+yenRNWDjgGlNDeGU94k1Pqtikj6bJKyyibjD5I+EBXrMKFbo/iFJjFm5FiS569FoXHK1kJAZmyjS2MzHZ4G95mCACN8tY6qLzh4WTy6IVU3nnZmb7Ay451qV+P9aF9tYPVzmoG5aKeYPvbVg== 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-SenderADCheck; bh=ucf0PrV9wVTDTI6RbUlRhSXT/2DUBfX6QoNkxvQWEtI=; b=jwppT9twx4rkMr3bNx+4ZGgxr3PiCWVs8QDMM4TzxdmjdDBHJayOaUhn0xpUlqNxp4qnKAqQ3OSoJWulqdYHKrHQAoeld1FLsTvjtbHk5oQsdGXOccMDdcrkfDsI5qpNfeEGfaG9ordjj+doWvwcNpKYIH8vojpfy5AYhrIuiqlrlYoXeFKIR8X6ueHgBZ0Ti7uGmX57oom+0GLTcL1sw45nsmm4jGVenA0RhHUXWj5+Kalp/t1kyDy0Qs3t3uWAsQ08CFbDKj0YmWwUyCv3x0yaDt73lmwZd5+asn2bl7lAe3Sn0kSsiJcAp1bpVaJyd119l9rb4gjfih/ER8l8dg== 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=amdcloud.onmicrosoft.com; s=selector2-amdcloud-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=ucf0PrV9wVTDTI6RbUlRhSXT/2DUBfX6QoNkxvQWEtI=; b=C5JENQYqOZbmtta/pZjREfRNFf+2HVYqWTSU87/YdKGJtTaJfvBFwC9FBH2gz9JPw/jcDH9OVsUJ67wjIpU+ZxDEdHRoNS+1idiimnzWnZLVolIQBv00zH9c6lxiuy+jfpiitP1d/a11ia2zbd+WnZzW8p+ztnNrG6ioMA14E9E= 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 DM5PR12MB1355.namprd12.prod.outlook.com (10.168.234.7) by DM6PR12MB4155.namprd12.prod.outlook.com (10.141.8.79) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3654.15; Tue, 15 Dec 2020 20:52:47 +0000 Received: from DM5PR12MB1355.namprd12.prod.outlook.com ([fe80::d95e:b9d:1d6a:e845]) by DM5PR12MB1355.namprd12.prod.outlook.com ([fe80::d95e:b9d:1d6a:e845%12]) with mapi id 15.20.3654.025; Tue, 15 Dec 2020 20:52:47 +0000 From: "Lendacky, Thomas" To: devel@edk2.groups.io CC: Brijesh Singh , James Bottomley , Jordan Justen , Laszlo Ersek , Ard Biesheuvel Subject: [PATCH 10/12] OvmfPkg/VmgExitLib: Support nested #VCs Date: Tue, 15 Dec 2020 14:51:09 -0600 Message-ID: <8d981134522af3a1efa222b12f36d5e831f88f2e.1608065471.git.thomas.lendacky@amd.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: References: X-Originating-IP: [165.204.77.1] X-ClientProxiedBy: CH2PR03CA0006.namprd03.prod.outlook.com (2603:10b6:610:59::16) To DM5PR12MB1355.namprd12.prod.outlook.com (2603:10b6:3:6e::7) Return-Path: thomas.lendacky@amd.com MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from tlendack-t1.amd.com (165.204.77.1) by CH2PR03CA0006.namprd03.prod.outlook.com (2603:10b6:610:59::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3654.12 via Frontend Transport; Tue, 15 Dec 2020 20:52:46 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: 89756895-dad9-4a50-53ce-08d8a13b60b1 X-MS-TrafficTypeDiagnostic: DM6PR12MB4155: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:10000; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: kRDLfARKeRCVVVovlEUWSoYIBeOS2yxoqMMlC7zheZkA4S7LGBLVXulCk4+JxrhV+P+v/FmYOGJPsfHmVleFwWrmcimeyWSNW/s4IIaoNBi4LMI5RTkMac9FtN+alhdKE8X/Hu3w2dOtxHhVGsxE2CRw/gn6jvvRnxPMwOOzJ/cSFNqiLGmkrg+Uke5y/yTXCkrFZrONu8xryo4EnvgZTlLxwEGJzZbUDNVmqE/xs1T5Ky/bJjOE9tAJ7iXt4/LhP2hhD3jYDLwJn9mhk4xX5SXhSAylhv6I3WackWhSUJeQVnbivu79z3jHmF8Or08vxJE656ysLoaO2RgcjJSHXi/W9hj4/K8fPe6kzKgxxoYf19Rf16kqNhPNJcdf1TuBeQEifRPq5BdEvtXJ85EQ7GkpSCUrn2m83z4SNmLOe2PN8y9d/jBwnHjT/Y3fAmQ2r567tuYXyY2lhTE9SFTvKw== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DM5PR12MB1355.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(4636009)(376002)(366004)(136003)(346002)(66946007)(26005)(4326008)(19627235002)(16526019)(6916009)(8676002)(36756003)(508600001)(52116002)(30864003)(6666004)(83380400001)(5660300002)(8936002)(966005)(186003)(54906003)(956004)(2616005)(66476007)(2906002)(86362001)(34490700003)(6486002)(66556008)(7696005);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData: =?us-ascii?Q?NCZCxGgOyc1osjcNoV/7VlUNAODDBFVnW3gIdy1oIsIKsmVHAX3XBsUNfoA5?= =?us-ascii?Q?oeSMWCn2+YiYew4jmYt86pXuUZCFuShlQptfKCjADANS9LWsP1fEqjLcr2jt?= =?us-ascii?Q?YPuW6nshBYiHT0cElH65JuN9ZQfhO19qQ9Qk7HiP3KGPgwmuhFMCCiD2/5pR?= =?us-ascii?Q?rtuVam8qvEgAsS957pbAPsR4xtV/hRTHXDUf8UL0cGoPKQXMF89G49cCLG3a?= =?us-ascii?Q?ixR3SzrA5IZpsZhb+EW7C1FMLoLpMpUUtUCq0Ri2clOt+WZyMEurGNBa4Qer?= =?us-ascii?Q?Ol/bKSCZJpHOPlmUvQeWPB1Fe1an+knlIY6ZJujTsVbQP32bjCOIWJnmcRax?= =?us-ascii?Q?5SzYRQM2dNmTVl8T0Uv0wZz3Qmewy5tyuczLtfa/sf8X5x5woZQ5o8MxO82B?= =?us-ascii?Q?WpLaeIoL8xGC6zXkrqTd1edPEdv/35351GUDBvJR0ziU320LctZVpeQt8ZWD?= =?us-ascii?Q?60WKhm/o/9Ng4xiSYwkNbrQ37hYjzMEAcatlq5d7y6c/at861MVPbqXdKSiu?= =?us-ascii?Q?VMtOrqZkmMX5fZ5OEOrgT6dCWw+PosJdlDZ6A3Wu0NPwWMbR3h9f4OxNrCrz?= =?us-ascii?Q?NUJjnm//Tujz6vs/YsxA+tZPEakPq+FXJPav27om1Bt7/7q7y9O7BgXRuwl3?= =?us-ascii?Q?z61rAZRgQC1YP908arDJMyNEHlH2oHvvxyplw1kjRavBhVhk19BijPAsf4e8?= =?us-ascii?Q?ZHNa2MyLY4jC5VjA0+ZwjcwnprSLYpix/Jg/2HZ0tOPPa9GjpStxEtTjXdH+?= =?us-ascii?Q?F8tQG0s08qMNpW45zycacmQUdlYPxU/piWJiptbKe6BkM9yFc3hR1bi0/9HE?= =?us-ascii?Q?3j4gEs+Pmsv070tzwThZnhVr7LoR9gxozDK896smNlvCoN8kOba7T3pS9web?= =?us-ascii?Q?wr3qdGs+EX1A4HPXCVUeXPDW3E14jmyXtNKDnx85ciYkoeEMREuJ5Mqul9vf?= =?us-ascii?Q?bvwypzfAKgtWMbiqcWaiNt7KIyZHjoJCWEB36HZ3iGFqPMDHo6R4E9+5Pxwr?= =?us-ascii?Q?IU8D?= X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-AuthSource: DM5PR12MB1355.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Dec 2020 20:52:46.9282 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-Network-Message-Id: 89756895-dad9-4a50-53ce-08d8a13b60b1 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: s+OUR+0lDitOXaxvFPABG9vXw+lOjgc8Yf9uWqi8L2D0YZZYbbAYHZuL5eVmzVVNZyB0Ef80xz+BXAA4qCTRBw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR12MB4155 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable From: Tom Lendacky BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3108 In order to be able to issue messages or make interface calls that cause another #VC (e.g. GetLocalApicBaseAddress () issues RDMSR), add support for nested #VCs. In order to support nested #VCs, GHCB backup pages are required. If a #VC is received while currently processing a #VC, a backup of the current GHCB content is made. This allows the #VC handler to continue processing the new #VC. Upon completion of the new #VC, the GHCB is restored from the backup page. The #VC recursion level is tracked in the per-vCPU variable area. Support is added to handle up to one nested #VC (or two #VCs total). If a second nested #VC is encountered, an ASSERT will be issued and the vCPU will enter CpuDeadLoop (). For SEC, the GHCB backup pages are reserved in the OvmfPkgX64.fdf memory layout, with two new fixed PCDs to provide the address and size of the backup area. For PEI/DXE, the GHCB backup pages are allocated as boot services pages using the memory allocation library. Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Cc: Brijesh Singh Signed-off-by: Tom Lendacky --- OvmfPkg/OvmfPkg.dec | 2 + OvmfPkg/AmdSev/AmdSevX64.dsc | 1 + OvmfPkg/OvmfPkgX64.dsc | 1 + OvmfPkg/AmdSev/AmdSevX64.fdf | 3 + OvmfPkg/OvmfPkgX64.fdf | 3 + OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf | 43 +++++++ OvmfPkg/Library/VmgExitLib/VmgExitLib.inf | 4 +- OvmfPkg/Include/Library/MemEncryptSevLib.h | 23 ++++ OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h | 53 +++++++++ .../VmgExitLib/PeiDxeVmgExitVcHandler.c | 103 +++++++++++++++++ .../Library/VmgExitLib/SecVmgExitVcHandler.c | 109 ++++++++++++++++++ OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c | 48 ++++---- OvmfPkg/PlatformPei/AmdSev.c | 38 +++++- 13 files changed, 404 insertions(+), 27 deletions(-) create mode 100644 OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf create mode 100644 OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h create mode 100644 OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c create mode 100644 OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 8a294116efaa..9731f09381a9 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -304,6 +304,8 @@ [PcdsFixedAtBuild] ## The base address of the SEC GHCB page used by SEV-ES. gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase|0|UINT32|0x40 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize|0|UINT32|0x41 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|0|UINT32|0x44 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize|0|UINT32|0x45 =20 ## The base address and size of the SEV Launch Secret Area provisioned # after remote attestation. If this is set in the .fdf, the platform diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc index c742ec54cb57..3e5a3f648ad5 100644 --- a/OvmfPkg/AmdSev/AmdSevX64.dsc +++ b/OvmfPkg/AmdSev/AmdSevX64.dsc @@ -236,6 +236,7 @@ [LibraryClasses.common.SEC] !else CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiC= puExceptionHandlerLib.inf !endif + VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf =20 [LibraryClasses.common.PEI_CORE] HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 3e008855fbc1..226b576545a9 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -264,6 +264,7 @@ [LibraryClasses.common.SEC] !else CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiC= puExceptionHandlerLib.inf !endif + VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf =20 [LibraryClasses.common.PEI_CORE] HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf diff --git a/OvmfPkg/AmdSev/AmdSevX64.fdf b/OvmfPkg/AmdSev/AmdSevX64.fdf index e8fd4b8c7b89..c0098502aa90 100644 --- a/OvmfPkg/AmdSev/AmdSevX64.fdf +++ b/OvmfPkg/AmdSev/AmdSevX64.fdf @@ -62,6 +62,9 @@ [FD.MEMFD] 0x00C000|0x001000 gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGu= id.PcdSevLaunchSecretSize =20 +0x00D000|0x001000 +gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpace= Guid.PcdOvmfSecGhcbBackupSize + 0x010000|0x010000 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpace= Guid.PcdOvmfSecPeiTempRamSize =20 diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf index 17ba9e177ac3..31fe58566bb5 100644 --- a/OvmfPkg/OvmfPkgX64.fdf +++ b/OvmfPkg/OvmfPkgX64.fdf @@ -85,6 +85,9 @@ [FD.MEMFD] 0x00B000|0x001000 gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase|gUefiCpuPkgTokenSpaceGuid.P= cdSevEsWorkAreaSize =20 +0x00C000|0x001000 +gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpace= Guid.PcdOvmfSecGhcbBackupSize + 0x010000|0x010000 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpace= Guid.PcdOvmfSecPeiTempRamSize =20 diff --git a/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf b/OvmfPkg/Library= /VmgExitLib/SecVmgExitLib.inf new file mode 100644 index 000000000000..df14de3c21bc --- /dev/null +++ b/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf @@ -0,0 +1,43 @@ +## @file +# VMGEXIT Support Library. +# +# Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D SecVmgExitLib + FILE_GUID =3D dafff819-f86c-4cff-a70e-83161e5bcf9a + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D VmgExitLib|SEC + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D X64 +# + +[Sources.common] + VmgExitLib.c + VmgExitVcHandler.c + VmgExitVcHandler.h + SecVmgExitVcHandler.c + +[Packages] + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + UefiCpuPkg/UefiCpuPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + PcdLib + +[FixedPcd] + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize + diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf b/OvmfPkg/Library/Vm= gExitLib/VmgExitLib.inf index d003ac63173e..b3c3e56ecff8 100644 --- a/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf +++ b/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf @@ -12,7 +12,7 @@ [Defines] FILE_GUID =3D 0e923c25-13cd-430b-8714-ffe85652a97b MODULE_TYPE =3D BASE VERSION_STRING =3D 1.0 - LIBRARY_CLASS =3D VmgExitLib + LIBRARY_CLASS =3D VmgExitLib|PEIM DXE_CORE DXE_DRIVER D= XE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER =20 # # The following information is for reference only and not required by the = build tools. @@ -23,6 +23,8 @@ [Defines] [Sources.common] VmgExitLib.c VmgExitVcHandler.c + VmgExitVcHandler.h + PeiDxeVmgExitVcHandler.c =20 [Packages] MdePkg/MdePkg.dec diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/L= ibrary/MemEncryptSevLib.h index 421b2e2c2c1e..eb400387e8e2 100644 --- a/OvmfPkg/Include/Library/MemEncryptSevLib.h +++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h @@ -13,6 +13,29 @@ =20 #include =20 +// +// Define the maximum number of #VCs allowed (e.g. the level of nesting +// that is allowed =3D> 2 allows for 1 nested #VCs). I this value is chang= ed, +// be sure to increase the size of +// gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize +// in any FDF file using this PCD. +// +#define VMGEXIT_MAXIMUM_VC_COUNT 2 + +// +// Per-CPU data mapping structure +// Use UINT32 for cached indicators and compare to a specific value +// so that the hypervisor can't indicate a value is cached by just +// writing random data to that area. +// +typedef struct { + UINT32 Dr7Cached; + UINT64 Dr7; + + UINTN VcCount; + VOID *GhcbBackupPages; +} SEV_ES_PER_CPU_DATA; + // // Internal structure for holding SEV-ES information needed during SEC pha= se // and valid only during SEC phase and early PEI during platform diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h b/OvmfPkg/Librar= y/VmgExitLib/VmgExitVcHandler.h new file mode 100644 index 000000000000..3a37cb04f616 --- /dev/null +++ b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h @@ -0,0 +1,53 @@ +/** @file + X64 #VC Exception Handler functon header file. + + Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __VMG_EXIT_VC_HANDLER_H__ +#define __VMG_EXIT_VC_HANDLER_H__ + +#include +#include +#include + +/** + Handle a #VC exception. + + Performs the necessary processing to handle a #VC exception. + + @param[in, out] Ghcb Pointer to the GHCB + @param[in, out] ExceptionType Pointer to an EFI_EXCEPTION_TYPE to be s= et + as value to use on error. + @param[in, out] SystemContext Pointer to EFI_SYSTEM_CONTEXT + + @retval EFI_SUCCESS Exception handled + @retval EFI_UNSUPPORTED #VC not supported, (new) exception value= to + propagate provided + @retval EFI_PROTOCOL_ERROR #VC handling failed, (new) exception val= ue to + propagate provided + +**/ +EFI_STATUS +EFIAPI +InternalVmgExitHandleVc ( + IN OUT GHCB *Ghcb, + IN OUT EFI_EXCEPTION_TYPE *ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ); + +/** + Routine to allow ASSERT from within #VC. + + @param[in, out] SevEsData Pointer to the per-CPU data + +**/ +VOID +EFIAPI +VmgExitIssueAssert ( + IN OUT SEV_ES_PER_CPU_DATA *SevEsData + ); + +#endif diff --git a/OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c b/OvmfPkg/= Library/VmgExitLib/PeiDxeVmgExitVcHandler.c new file mode 100644 index 000000000000..fb4942df37ca --- /dev/null +++ b/OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c @@ -0,0 +1,103 @@ +/** @file + X64 #VC Exception Handler functon. + + Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include + +#include "VmgExitVcHandler.h" + +/** + Handle a #VC exception. + + Performs the necessary processing to handle a #VC exception. + + @param[in, out] ExceptionType Pointer to an EFI_EXCEPTION_TYPE to be s= et + as value to use on error. + @param[in, out] SystemContext Pointer to EFI_SYSTEM_CONTEXT + + @retval EFI_SUCCESS Exception handled + @retval EFI_UNSUPPORTED #VC not supported, (new) exception value= to + propagate provided + @retval EFI_PROTOCOL_ERROR #VC handling failed, (new) exception val= ue to + propagate provided + +**/ +EFI_STATUS +EFIAPI +VmgExitHandleVc ( + IN OUT EFI_EXCEPTION_TYPE *ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ) +{ + MSR_SEV_ES_GHCB_REGISTER Msr; + GHCB *Ghcb; + GHCB *GhcbBackup; + EFI_STATUS VcRet; + BOOLEAN InterruptState; + SEV_ES_PER_CPU_DATA *SevEsData; + + InterruptState =3D GetInterruptState (); + if (InterruptState) { + DisableInterrupts (); + } + + Msr.GhcbPhysicalAddress =3D AsmReadMsr64 (MSR_SEV_ES_GHCB); + ASSERT (Msr.GhcbInfo.Function =3D=3D 0); + ASSERT (Msr.Ghcb !=3D 0); + + Ghcb =3D Msr.Ghcb; + GhcbBackup =3D NULL; + + SevEsData =3D (SEV_ES_PER_CPU_DATA *) (Ghcb + 1); + SevEsData->VcCount++; + + // + // Check for maximum PEI/DXE #VC nesting. + // + if (SevEsData->VcCount > VMGEXIT_MAXIMUM_VC_COUNT) { + VmgExitIssueAssert (SevEsData); + } else if (SevEsData->VcCount > 1) { + // + // Nested #VC + // + if (SevEsData->GhcbBackupPages =3D=3D NULL) { + VmgExitIssueAssert (SevEsData); + } + + // + // Save the active GHCB to a backup page. + // To access the correct backup page, increment the backup page poin= ter + // based on the current VcCount. + // + GhcbBackup =3D (GHCB *) SevEsData->GhcbBackupPages; + GhcbBackup +=3D (SevEsData->VcCount - 2); + + CopyMem (GhcbBackup, Ghcb, sizeof (*Ghcb)); + } + + VcRet =3D InternalVmgExitHandleVc (Ghcb, ExceptionType, SystemContext); + + if (GhcbBackup !=3D NULL) { + // + // Restore the active GHCB from the backup page. + // + CopyMem (Ghcb, GhcbBackup, sizeof (*Ghcb)); + } + + SevEsData->VcCount--; + + if (InterruptState) { + EnableInterrupts (); + } + + return VcRet; +} diff --git a/OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c b/OvmfPkg/Lib= rary/VmgExitLib/SecVmgExitVcHandler.c new file mode 100644 index 000000000000..85853d334b35 --- /dev/null +++ b/OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c @@ -0,0 +1,109 @@ +/** @file + X64 #VC Exception Handler functon. + + Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include + +#include "VmgExitVcHandler.h" + +/** + Handle a #VC exception. + + Performs the necessary processing to handle a #VC exception. + + @param[in, out] ExceptionType Pointer to an EFI_EXCEPTION_TYPE to be s= et + as value to use on error. + @param[in, out] SystemContext Pointer to EFI_SYSTEM_CONTEXT + + @retval EFI_SUCCESS Exception handled + @retval EFI_UNSUPPORTED #VC not supported, (new) exception value= to + propagate provided + @retval EFI_PROTOCOL_ERROR #VC handling failed, (new) exception val= ue to + propagate provided + +**/ +EFI_STATUS +EFIAPI +VmgExitHandleVc ( + IN OUT EFI_EXCEPTION_TYPE *ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ) +{ + MSR_SEV_ES_GHCB_REGISTER Msr; + GHCB *Ghcb; + GHCB *GhcbBackup; + EFI_STATUS VcRet; + BOOLEAN InterruptState; + SEV_ES_PER_CPU_DATA *SevEsData; + + InterruptState =3D GetInterruptState (); + if (InterruptState) { + DisableInterrupts (); + } + + Msr.GhcbPhysicalAddress =3D AsmReadMsr64 (MSR_SEV_ES_GHCB); + ASSERT (Msr.GhcbInfo.Function =3D=3D 0); + ASSERT (Msr.Ghcb !=3D 0); + + Ghcb =3D Msr.Ghcb; + GhcbBackup =3D NULL; + + SevEsData =3D (SEV_ES_PER_CPU_DATA *) (Ghcb + 1); + SevEsData->VcCount++; + + // + // Check for maximum SEC #VC nesting. + // + if (SevEsData->VcCount > VMGEXIT_MAXIMUM_VC_COUNT) { + VmgExitIssueAssert (SevEsData); + } else if (SevEsData->VcCount > 1) { + UINTN GhcbBackupSize; + + // + // Be sure that the proper amount of pages are allocated + // + GhcbBackupSize =3D (VMGEXIT_MAXIMUM_VC_COUNT - 1) * sizeof (*Ghcb); + if (GhcbBackupSize > FixedPcdGet32 (PcdOvmfSecGhcbBackupSize)) { + // + // Not enough SEC backup pages allocated. + // + VmgExitIssueAssert (SevEsData); + } + + // + // Save the active GHCB to a backup page. + // To access the correct backup page, increment the backup page poin= ter + // based on the current VcCount. + // + GhcbBackup =3D (GHCB *) FixedPcdGet32 (PcdOvmfSecGhcbBackupBase); + GhcbBackup +=3D (SevEsData->VcCount - 2); + + CopyMem (GhcbBackup, Ghcb, sizeof (*Ghcb)); + } + + VcRet =3D InternalVmgExitHandleVc (Ghcb, ExceptionType, SystemContext); + + if (GhcbBackup !=3D NULL) { + // + // Restore the active GHCB from the backup page. + // + CopyMem (Ghcb, GhcbBackup, sizeof (*Ghcb)); + } + + SevEsData->VcCount--; + + if (InterruptState) { + EnableInterrupts (); + } + + return VcRet; +} diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c b/OvmfPkg/Librar= y/VmgExitLib/VmgExitVcHandler.c index 5149ab2bc989..ce577e4677eb 100644 --- a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c +++ b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c @@ -9,11 +9,14 @@ #include #include #include +#include #include #include #include #include =20 +#include "VmgExitVcHandler.h" + // // Instruction execution mode definition // @@ -126,18 +129,6 @@ UINT64 SEV_ES_INSTRUCTION_DATA *InstructionData ); =20 -// -// Per-CPU data mapping structure -// Use UINT32 for cached indicators and compare to a specific value -// so that the hypervisor can't indicate a value is cached by just -// writing random data to that area. -// -typedef struct { - UINT32 Dr7Cached; - UINT64 Dr7; -} SEV_ES_PER_CPU_DATA; - - /** Return a pointer to the contents of the specified register. =20 @@ -1546,6 +1537,7 @@ Dr7ReadExit ( =20 Performs the necessary processing to handle a #VC exception. =20 + @param[in, out] Ghcb Pointer to the GHCB @param[in, out] ExceptionType Pointer to an EFI_EXCEPTION_TYPE to be s= et as value to use on error. @param[in, out] SystemContext Pointer to EFI_SYSTEM_CONTEXT @@ -1559,14 +1551,13 @@ Dr7ReadExit ( **/ EFI_STATUS EFIAPI -VmgExitHandleVc ( +InternalVmgExitHandleVc ( + IN OUT GHCB *Ghcb, IN OUT EFI_EXCEPTION_TYPE *ExceptionType, IN OUT EFI_SYSTEM_CONTEXT SystemContext ) { - MSR_SEV_ES_GHCB_REGISTER Msr; EFI_SYSTEM_CONTEXT_X64 *Regs; - GHCB *Ghcb; NAE_EXIT NaeExit; SEV_ES_INSTRUCTION_DATA InstructionData; UINT64 ExitCode, Status; @@ -1575,12 +1566,7 @@ VmgExitHandleVc ( =20 VcRet =3D EFI_SUCCESS; =20 - Msr.GhcbPhysicalAddress =3D AsmReadMsr64 (MSR_SEV_ES_GHCB); - ASSERT (Msr.GhcbInfo.Function =3D=3D 0); - ASSERT (Msr.Ghcb !=3D 0); - Regs =3D SystemContext.SystemContextX64; - Ghcb =3D Msr.Ghcb; =20 VmgInit (Ghcb, &InterruptState); =20 @@ -1670,3 +1656,25 @@ VmgExitHandleVc ( =20 return VcRet; } + +/** + Routine to allow ASSERT from within #VC. + + @param[in, out] SevEsData Pointer to the per-CPU data + +**/ +VOID +EFIAPI +VmgExitIssueAssert ( + IN OUT SEV_ES_PER_CPU_DATA *SevEsData + ) +{ + // + // Progress will be halted, so set VcCount to allow for ASSERT output + // to be seen. + // + SevEsData->VcCount =3D 0; + + ASSERT (FALSE); + CpuDeadLoop (); +} diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c index 954d53eba4e8..dddffdebda4b 100644 --- a/OvmfPkg/PlatformPei/AmdSev.c +++ b/OvmfPkg/PlatformPei/AmdSev.c @@ -33,12 +33,17 @@ AmdSevEsInitialize ( VOID ) { - VOID *GhcbBase; - PHYSICAL_ADDRESS GhcbBasePa; - UINTN GhcbPageCount, PageCount; - RETURN_STATUS PcdStatus, DecryptStatus; - IA32_DESCRIPTOR Gdtr; - VOID *Gdt; + UINT8 *GhcbBase; + PHYSICAL_ADDRESS GhcbBasePa; + UINTN GhcbPageCount; + UINT8 *GhcbBackupBase; + UINT8 *GhcbBackupPages; + UINTN GhcbBackupPageCount; + SEV_ES_PER_CPU_DATA *SevEsData; + UINTN PageCount; + RETURN_STATUS PcdStatus, DecryptStatus; + IA32_DESCRIPTOR Gdtr; + VOID *Gdt; =20 if (!MemEncryptSevEsIsEnabled ()) { return; @@ -84,6 +89,27 @@ AmdSevEsInitialize ( "SEV-ES is enabled, %lu GHCB pages allocated starting at 0x%p\n", (UINT64)GhcbPageCount, GhcbBase)); =20 + // + // Allocate #VC recursion backup pages. The number of backup pages neede= d is + // one less than the maximum VC count. + // + GhcbBackupPageCount =3D mMaxCpuCount * (VMGEXIT_MAXIMUM_VC_COUNT - 1); + GhcbBackupBase =3D AllocatePages (GhcbBackupPageCount); + ASSERT (GhcbBackupBase !=3D NULL); + + GhcbBackupPages =3D GhcbBackupBase; + for (PageCount =3D 1; PageCount < GhcbPageCount; PageCount +=3D 2) { + SevEsData =3D + (SEV_ES_PER_CPU_DATA *)(GhcbBase + EFI_PAGES_TO_SIZE (PageCount)); + SevEsData->GhcbBackupPages =3D GhcbBackupPages; + + GhcbBackupPages +=3D EFI_PAGE_SIZE * (VMGEXIT_MAXIMUM_VC_COUNT - 1); + } + + DEBUG ((DEBUG_INFO, + "SEV-ES is enabled, %lu GHCB backup pages allocated starting at 0x%p\n= ", + (UINT64)GhcbBackupPageCount, GhcbBackupBase)); + AsmWriteMsr64 (MSR_SEV_ES_GHCB, GhcbBasePa); =20 // --=20 2.28.0