From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from NAM01-SN1-obe.outbound.protection.outlook.com (mail-sn1nam01on0055.outbound.protection.outlook.com [104.47.32.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id AFBD621E1DAD9 for ; Thu, 3 Aug 2017 16:09:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amdcloud.onmicrosoft.com; s=selector1-amd-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=MYq0tEaPIIQp7REZFzz9FCbqah8GSIXYkkmjQ4g0wwE=; b=EeM1sSm5YlUAqC5tL4Gs5aO9gusvQkBaCAq78ssemlXze8wcCJA0i4sa1OKXCyrDJxQtBd8Q9VqZ+smguqc3vbEZ60qFIFrLTJBZXFbJKYnUlErBDnRz2YnIDIlaBk8z8DevNvKo+CO4sJlJfbTis7XfSQX49w609dI/TQywers= Received: from brijesh-build-machine.amd.com (165.204.77.1) by BY2PR12MB0148.namprd12.prod.outlook.com (10.162.82.21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.1.1304.22; Thu, 3 Aug 2017 23:11:24 +0000 From: Brijesh Singh To: edk2-devel@lists.01.org Cc: Tom Lendacky , Brijesh Singh , Jordan Justen , Laszlo Ersek Date: Thu, 3 Aug 2017 19:11:12 -0400 Message-Id: <1501801872-22626-2-git-send-email-brijesh.singh@amd.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1501801872-22626-1-git-send-email-brijesh.singh@amd.com> References: <1501801872-22626-1-git-send-email-brijesh.singh@amd.com> MIME-Version: 1.0 X-Originating-IP: [165.204.77.1] X-ClientProxiedBy: BN6PR13CA0048.namprd13.prod.outlook.com (10.171.172.34) To BY2PR12MB0148.namprd12.prod.outlook.com (10.162.82.21) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 848b9fef-5e67-4910-4cfa-08d4dac4f690 X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(300000500095)(300135000095)(300000501095)(300135300095)(22001)(300000502095)(300135100095)(2017030254152)(300000503095)(300135400095)(48565401081)(201703131423075)(201703031133081)(201702281549075)(300000504095)(300135200095)(300000505095)(300135600095)(300000506095)(300135500095); SRVR:BY2PR12MB0148; X-Microsoft-Exchange-Diagnostics: 1; BY2PR12MB0148; 3:bY9KznHVpg66YV91lOCIlr655vptUaP6EQTOqVQ+pH0PVkQxPUmLrrIpQzsewfdB71S1OXj3E5PTuSTY3shvmXkemMI0ML85MF1y8TljDIymIyGh28jyOKfe8bcG4OF0H92BGDGC43LRakkle1Ai+59hvVNMPZr7jiJypAD2JGtVvD88R3q2y7q98VY9qurkh4wR71sPkPPk08EDJKEGbkXkYesOzlQFCfDDB/irErayLdnqs1HfabzQK0Qq3PcX; 25:S9jD+cs0J7FK7sZ0JKuY9qpTTKffvgSuvWDiS7XMb+9RbScMsM6IGCgpX4LZV96xg47W76hiRgGDEZjn3/N9CxjS2B+EVowqQiS/R8XG95Y4RS+iJrQ0bx9MXyG2nH5eorGWVmAGfoZXTaVjvEzTy8Yhn3siXFLIM9+79GDVWkxYvjeA4bKQ0siP6ZTKtjgx7CEwPzyTIm2RJdO/JRU6TWswcli7MWPH6OCei4XC5dcMwa/7s5RTiCUnEv8QuQTy8Uf3CTIvs5nZYCnSooD2fV9Faj1TrXqtF3pq57/cWYTIEIOpYU09biRtyzyJxV9BbBBzrK4SwHaLCZ/R8Z1x5g==; 31:CHJshG7/Jhf2M6+IJR8BCs3gL+yCNJsvU6ZnC7lvIAkO2bIfr66QRB5yR5bfs7mdAkXM0gQSBEFMKA307mjagFx3dPrtUWvv1sQzMXEAiQE8MULbngahAVS1uB/8SWgSU6Cu4rPws0+CQvKrE08eg4zekIcLH468l1pi74CzMg5KXEUmbAnCG/mS9K/yGCbPkia1BwHl9AZGm4oG1n4p+nXmsz2pP+klNBMGpWl05yo= X-MS-TrafficTypeDiagnostic: BY2PR12MB0148: X-Microsoft-Exchange-Diagnostics: 1; BY2PR12MB0148; 20:rEa53WdTVVD2ly4BeBuqRC2BrwKn1TJR7aHnIaJVi8FWOXK5HYKn/kJl1VhB6b7eGozedWWsSGSZttonmHHe5pG4vtw4mXmxx/Ln5CLHAY8kdYJvdi97+saRiQLVa7ublSi8xDSo8n/Uwb6VLxlYW17tZNuM0a3xxb8wZj0ILrPCm42jRxFqUYn6m4mGRNgaFWLA3PVwaPkR4quUN0DUOQaXQiPLswsI4QZWGhwmHvEMA+N/x11DVF5Dn0vwjdrt6tICndQTEoMsPk8DMfiGI3J8d1UrAQzmbpg6Be/h9CrTo/QpuOQa8rY9RI5tj/K+HJk+0pZ2m3k3eJRSdPgtjhul1iBr3OQH2ggEzjsgYUHDP1d0BzAfjnFUzBUS0/1dUDiYknUdGm4V+DFv0XKKWcDCSo78hGw1AsYzbS6ge7ihNheCfOrCKD+0mttUHYc7imUBZTEoJiJKIuaxm6U4FczYQg7T36GbPtiB0eoT3dKmV5XXb4RvNihcPj8ru4LN; 4:5HD+aDMwUUJXqnx3YSB7rSMoQCEDQ2aqx/pWhW5rH9FhNqTS0M+huoWiu+b0InSW7lDe/+ObUNh+tlkXaROKcL3K0Uhim9lcGKcJxZ0mE3BkScCfXDYJh/6ymN9cIy2VmZaZNnhGAOdKaGZuOToHw8lVirkEZzMV0Kw1SZxRKJ95E15TCuAETyPerNEncSMK8LGmsdLfMVNI8xrGgghHw2vh97m6SzmH14rX0VuOTjFPMHvplJpD63MxCsIIAnoVSvotJXf73HbRU+h+eSFZfOmaGiL8uIr+Ec9YRp4ZpcgS8m4ow8mw1ID3Cqk/QxiJUTdPvXQ7+/dKxwQXJZR9wy+taNyCPdxtNL3t7W0qWGw= X-Exchange-Antispam-Report-Test: UriScan:(767451399110)(162533806227266)(228905959029699); X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(601004)(2401047)(8121501046)(5005006)(10201501046)(3002001)(93006095)(93001095)(100000703101)(100105400095)(6055026)(6041248)(20161123564025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123555025)(20161123558100)(20161123560025)(20161123562025)(6072148)(100000704101)(100105200095)(100000705101)(100105500095); SRVR:BY2PR12MB0148; BCL:0; PCL:0; RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095); SRVR:BY2PR12MB0148; X-Forefront-PRVS: 03883BD916 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(7370300001)(4630300001)(6009001)(6029001)(39400400002)(39850400002)(39840400002)(39450400003)(39410400002)(189002)(199003)(105586002)(68736007)(305945005)(2950100002)(86362001)(53936002)(6916009)(25786009)(7736002)(42186005)(53416004)(106356001)(36756003)(4326008)(5003940100001)(6666003)(33646002)(66066001)(2906002)(47776003)(54906002)(6306002)(6116002)(3846002)(966005)(2351001)(2361001)(189998001)(110136004)(76176999)(81166006)(81156014)(38730400002)(478600001)(50226002)(8676002)(6486002)(97736004)(101416001)(50466002)(48376002)(7350300001)(50986999)(5660300001)(19627235001); DIR:OUT; SFP:1101; SCL:1; SRVR:BY2PR12MB0148; H:brijesh-build-machine.amd.com; FPR:; SPF:None; PTR:InfoNoRecords; MX:1; A:1; LANG:en; Received-SPF: None (protection.outlook.com: amd.com does not designate permitted sender hosts) Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=brijesh.singh@amd.com; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BY2PR12MB0148; 23:z9/UDXjIbHDsRLbiPoTtNxgqYuaGwkJmGEXK8M0gC?= =?us-ascii?Q?n6MMMWJbTRd8HweLuoPUdkW1WcbsRwHlQ04ACWTFtW8Jd5QvboAKO9FiN0DA?= =?us-ascii?Q?jQC0tzGGC9ZlsvTDExiXLVMv4G3kq5s+zloOOJ1W1KGsho1C2kqVfUbsB1Rh?= =?us-ascii?Q?N584PTevPd9g1m6VR74vsDj38NGHyDoc1yvXrHf/oUCc2KtoHZkEAE+E/mM8?= =?us-ascii?Q?sl7RT2+i/sPoBPiVqeQkCbDZQAW68nkrsGOH5wzpB/BURYOVq69owLlA81iw?= =?us-ascii?Q?qZWSafd91SA3qBzJBBS/oQfSys9ztYLfHzhc5SvC5wbS+T4VvqJOwTvu2auR?= =?us-ascii?Q?7+DtOlTlV+dCOPnu1TeUWoJu76M7oaTPVx8J19xgPH3uDA9Ug135ny3i840t?= =?us-ascii?Q?L203OpFF1C1xPrfRFERs3+4RdJFVluYrgvhNAMD45SOO3h1MCFlvF58GGe7Z?= =?us-ascii?Q?PBRlY8+dnKE4OQk18BxtcxDiprDdlYi9+jcHdnKN6S84cXlzRJuRRK4CYbMO?= =?us-ascii?Q?RDmNzy2FvX1cD1QVJImGM2v5fQY8g8KBJWrleo/powwV8+xvk8KOj7kfoVbP?= =?us-ascii?Q?pzhLT5O52GhzmKCbQQkAuuqwI7DrLsHBxH58+XqsNw5vUPu/Vo1DnTK6pQcT?= =?us-ascii?Q?bePV8EF3I1dLuDQZM4OL1Fv75LscAC4y02HoVEZXZq6poOXMX2lk90L9Lvzd?= =?us-ascii?Q?ngaJGYfNdGPEniHdbiaOQb8KpMRUlogH/LARl+J9l5qEaaZRZKeqNIxdHXaB?= =?us-ascii?Q?96u2bSsOiG5JAAPWiF8OEv1hA4JFrVNxLxmWEB0jBO5HAfscW4DvMA/SnWHu?= =?us-ascii?Q?rv5THoggxnQBiytEjK3Gk2ZHZAoRPLrH3NtYCMGFknQgA/CT9mBVx/uCs31C?= =?us-ascii?Q?OU4l+X9qEO2ThRr7UrQN5+sUXvMeLF8ZcMlmE6HMv3VYmETdMeoDGAsaFwsu?= =?us-ascii?Q?N067NB6TVwAnRVYh/WGp1vhVCS9GMJtM/ydYdjdK16nfFdZogenztYAYI/58?= =?us-ascii?Q?5xQe25i+WPznKWRa9F7VdqjIoey12aTOyV0Ipkii/G7bBKJxWE9YKxtM9oSq?= =?us-ascii?Q?4JK8mrTiF38smYMstHI2YI7oVI4iS+8GG0MZCUCOpX35w4MG7pgQ5P8S2rJg?= =?us-ascii?Q?oxWoPDkYUx71ZTGugiiNSxoTi9nS2I/WmJp0lz12+iG1ecxYXY65fRpQk7hX?= =?us-ascii?Q?21hLu0eFHxlT7vQnpn7wcKP/IqMHpF65U70gfs9JBCMarRU2DgAFyOkMMjlq?= =?us-ascii?Q?s52RMHwFTQBHWoTQHtyXTJMculjzxaPLQcOP5C89XYg5BNuttsiEB2YoFxsQ?= =?us-ascii?Q?+uS6fubP3sY7xacqhzx2qZyIzhaRPFX9lsjsNKFQONXqYuq+1HJSwg4B3oHv?= =?us-ascii?Q?TNzdA=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1; BY2PR12MB0148; 6:C73OHa3lqw7Y8b4L0yClKEgteTnRNJZNzbE1xNac9GwjVRuBgZnQMrnjtE8BjjCurcurq/2yRaMuX404xpWtETvzmyjC7aC9r6yT/ftExnVLqzl/qFSYJtqI6sFoPK17b7Uby1bYH/vnTUy6tAVb1BAiccpAonnXLTRPYugV2iCLtQH8j/mNyW96eC9US50LRgeHq3MDXUz00bdwSOTF2r6qKCC1d82vomh/djnqImHqmV+phN3AL/DKM+UPBAM6Nhj2AGRx1SPeWVq4VJdxDoGGSDQKzzBSiy9YMb/J3zl/543WLD1JjYT9TI6Ksl4oAXoEjLcRKK3TXOcanrTHZw==; 5:QZTk9hnFmo/d/u6IXG168T0b3LgM2plygjfZp5Yx63YFqaa0gfdedf/oRGIOUPgW6RQLI2RVDBCmN1sJbL8qlGcXbpCYwVIa59f95UmiNF/UAy6QHESK+AeYcMmUH6Agu0jB+dBLacMmzwrS4HJ/rw==; 24:YUejwiZV/U9MU5NQGYxVHAzgk+cFqL9V9zoZExSUOXcqVMRZdzpgdAuss8KomkY6A9nvJZcOCB7wWKI2xP5zsS54TIGQeE+9u0Kx5ImimNA=; 7:GKW/jtkA2dSktxzEflJIKriVG61q4bXN3f3nZ3sbFj3gLIDskDaSCqMjCssWmnLs7ucEf71SO6C/K7zxhGwQsUwBFNtpJuNMFLu9q1134X/vY35tiWRXWD/wxzSWe6Fcho7HGan+ZJ0KrBBcoboWTQQP9MD5sIW+WxCx7fKUjb5PZ7GQS4HTDPtrcMkm3RIjNynr3E6kdvcI7nM8WrwGx2uRZo+Pq27PPyCpFqPZ1d0= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; BY2PR12MB0148; 20:sk2WAtjPdc0oW0yu+Y9UZzapkTpXbNq12d3ioJa3eaB7IHgS+7Kjdkv92NWcevL4kuiK9s7SLdY8dQUZvLxTSP6UiQIZbLWwLSad9d18V+YuErKdXE5mV66xNA0s59qKo9AlFTahVQAFC8T1cU+jY1tCi0FsYi4bDkWgPl34Q4QWFX7VGtwr8j0gRqEtj6d30hHm90DBoa9TNW2C+lqn8e2fSiePVWeiIvb+2QFWRwYCjIgF7qZmNHwDXIYs5fKL X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 03 Aug 2017 23:11:24.3210 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY2PR12MB0148 Subject: [PATCH v3 1/1] OvmfPkg/QemuFwCfgLib: Use BusMasterCommonBuffer to map FW_CFG_DMA_ACCESS X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 03 Aug 2017 23:09:17 -0000 Content-Type: text/plain Commit 09719a01b11b (OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase) uses IOMMU protocol to allocate and free FW_CFG_DMA_ACCESS buffer when SEV is active. During initial commits we made assumption that IOMMU.AllocateBuffer() will provide PlainTextAddress (i.e C-bit cleared). This assumption was wrong, the AllocateBuffer() protocol member is not expected to produce a buffer that is immediatly usable, and client is required to call Map() uncondtionally with BusMasterCommonBuffer[64] to get a mapping which is accessable by both host and device. The patch refactors code a bit and add the support to Map() FW_CFG_DMA_ACCESS buffer using BusMasterCommonBuffer operation after allocation and Unamp() before free. The complete discussion about this and recommendation from Laszlo can be found here [1] [1] https://lists.01.org/pipermail/edk2-devel/2017-July/012652.html Suggested-by: Laszlo Ersek Cc: Jordan Justen Cc: Laszlo Ersek Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh --- OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h | 42 +-- OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c | 330 ++++++++++++++++---- OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c | 130 -------- OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c | 99 +++--- OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c | 58 +--- 5 files changed, 367 insertions(+), 292 deletions(-) diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h index 8cfa7913ffae..327f1d37e17d 100644 --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h @@ -45,39 +45,25 @@ InternalQemuFwCfgDmaIsAvailable ( ); /** - Returns a boolean indicating whether SEV support is enabled + Transfer an array of bytes, or skip a number of bytes, using the DMA + interface. - @retval TRUE SEV is enabled - @retval FALSE SEV is disabled -**/ -BOOLEAN -InternalQemuFwCfgSevIsEnabled ( - VOID - ); + @param[in] Size Size in bytes to transfer or skip. -/** - Allocate a bounce buffer for SEV DMA. - - @param[out] Buffer Allocated DMA Buffer pointer - @param[in] NumPage Number of pages. + @param[in,out] Buffer Buffer to read data into or write data from. Ignored, + and may be NULL, if Size is zero, or Control is + FW_CFG_DMA_CTL_SKIP. + @param[in] Control One of the following: + FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer. + FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer. + FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg. **/ VOID -InternalQemuFwCfgSevDmaAllocateBuffer ( - OUT VOID **Buffer, - IN UINT32 NumPages +InternalQemuFwCfgDmaBytes ( + IN UINT32 Size, + IN OUT VOID *Buffer OPTIONAL, + IN UINT32 Control ); -/** - Free the DMA buffer allocated using InternalQemuFwCfgSevDmaAllocateBuffer - - @param[in] NumPage Number of pages. - @param[in] Buffer DMA Buffer pointer - -**/ -VOID -InternalQemuFwCfgSevDmaFreeBuffer ( - IN VOID *Buffer, - IN UINT32 NumPages - ); #endif diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c index f8eb03bc3a9a..576941749cf2 100644 --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -31,20 +32,6 @@ STATIC BOOLEAN mQemuFwCfgSupported = FALSE; STATIC BOOLEAN mQemuFwCfgDmaSupported; STATIC EDKII_IOMMU_PROTOCOL *mIoMmuProtocol; -/** - - Returns a boolean indicating whether SEV is enabled - - @retval TRUE SEV is enabled - @retval FALSE SEV is disabled -**/ -BOOLEAN -InternalQemuFwCfgSevIsEnabled ( - VOID - ) -{ - return MemEncryptSevIsEnabled (); -} /** Returns a boolean indicating if the firmware configuration interface @@ -110,7 +97,8 @@ QemuFwCfgInitialize ( // IoMmuDxe driver must have installed the IOMMU protocol. If we are not // able to locate the protocol then something must have gone wrong. // - Status = gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **)&mIoMmuProtocol); + Status = gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, + (VOID **)&mIoMmuProtocol); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "QemuFwCfgSevDma %a:%a Failed to locate IOMMU protocol.\n", @@ -157,74 +145,308 @@ InternalQemuFwCfgDmaIsAvailable ( } /** - Allocate a bounce buffer for SEV DMA. - - @param[in] NumPage Number of pages. - @param[out] Buffer Allocated DMA Buffer pointer + Function is used for allocating a bi-directional FW_CFG_DMA_ACCESS used + between Host and device to exchange the information. The buffer must be free'd + using FreeFwCfgDmaAccessBuffer (). **/ +STATIC VOID -InternalQemuFwCfgSevDmaAllocateBuffer ( - OUT VOID **Buffer, - IN UINT32 NumPages +AllocFwCfgDmaAccessBuffer ( + OUT VOID **Access, + OUT VOID **MapInfo ) { - EFI_STATUS Status; + UINTN Size; + UINTN NumPages; + EFI_STATUS Status; + VOID *HostAddress; + EFI_PHYSICAL_ADDRESS DmaAddress; + VOID *Mapping; - ASSERT (mIoMmuProtocol != NULL); + Size = sizeof (FW_CFG_DMA_ACCESS); + NumPages = EFI_SIZE_TO_PAGES (Size); + // + // As per UEFI spec, in order to map a host address with + // BusMasterCommomBuffer64, the buffer must be allocated using the IOMMU + // AllocateBuffer() + // Status = mIoMmuProtocol->AllocateBuffer ( - mIoMmuProtocol, - 0, - EfiBootServicesData, - NumPages, - Buffer, - EDKII_IOMMU_ATTRIBUTE_MEMORY_CACHED - ); + mIoMmuProtocol, + AllocateAnyPages, + EfiBootServicesData, + NumPages, + &HostAddress, + EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE + ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, - "%a:%a failed to allocate %u pages\n", gEfiCallerBaseName, __FUNCTION__, - NumPages)); + "%a:%a failed to allocate FW_CFG_DMA_ACCESS\n", gEfiCallerBaseName, + __FUNCTION__)); ASSERT (FALSE); CpuDeadLoop (); } - DEBUG ((DEBUG_VERBOSE, - "%a:%a buffer 0x%Lx Pages %u\n", gEfiCallerBaseName, __FUNCTION__, - (UINT64)(UINTN)Buffer, NumPages)); + // + // Map the host buffer with BusMasterCommonBuffer64 + // + Status = mIoMmuProtocol->Map ( + mIoMmuProtocol, + EdkiiIoMmuOperationBusMasterCommonBuffer64, + HostAddress, + &Size, + &DmaAddress, + &Mapping + ); + if (EFI_ERROR (Status)) { + mIoMmuProtocol->FreeBuffer (mIoMmuProtocol, NumPages, HostAddress); + DEBUG ((DEBUG_ERROR, + "%a:%a failed to Map() FW_CFG_DMA_ACCESS\n", gEfiCallerBaseName, + __FUNCTION__)); + ASSERT (FALSE); + CpuDeadLoop (); + } + + if (Size < sizeof (FW_CFG_DMA_ACCESS)) { + mIoMmuProtocol->Unmap (mIoMmuProtocol, Mapping); + mIoMmuProtocol->FreeBuffer (mIoMmuProtocol, NumPages, HostAddress); + DEBUG ((DEBUG_ERROR, + "%a:%a failed to Map() - requested 0x%Lx got 0x%Lx\n", gEfiCallerBaseName, + __FUNCTION__, (UINT64)sizeof (FW_CFG_DMA_ACCESS), (UINT64)Size)); + ASSERT (FALSE); + CpuDeadLoop (); + } + + *Access = HostAddress; + *MapInfo = Mapping; } /** - Free the DMA buffer allocated using InternalQemuFwCfgSevDmaAllocateBuffer + Function is to used for freeing the Access buffer allocated using + AllocFwCfgDmaAccessBuffer() + +**/ +STATIC +VOID +FreeFwCfgDmaAccessBuffer ( + IN VOID *Access, + IN VOID *Mapping + ) +{ + UINTN NumPages; + EFI_STATUS Status; + + NumPages = EFI_SIZE_TO_PAGES (sizeof (FW_CFG_DMA_ACCESS)); + + Status = mIoMmuProtocol->Unmap (mIoMmuProtocol, Mapping); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, + "%a:%a failed to UnMap() Mapping 0x%Lx\n", gEfiCallerBaseName, + __FUNCTION__, (UINT64)Mapping)); + ASSERT (FALSE); + CpuDeadLoop (); + } - @param[in] NumPage Number of pages. - @param[in] Buffer DMA Buffer pointer + Status = mIoMmuProtocol->FreeBuffer (mIoMmuProtocol, NumPages, Access); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, + "%a:%a failed to Free() 0x%Lx\n", gEfiCallerBaseName, __FUNCTION__, + (UINT64) Access)); + ASSERT (FALSE); + CpuDeadLoop (); + } +} + +/** + Function is used for mapping host address to device address. The buffer must + be unmapped with UnmapDmaDataBuffer (). **/ +STATIC VOID -InternalQemuFwCfgSevDmaFreeBuffer ( - IN VOID *Buffer, - IN UINT32 NumPages +MapFwCfgDmaDataBuffer ( + IN BOOLEAN IsWrite, + IN VOID *HostAddress, + IN UINT32 Size, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **MapInfo ) { - EFI_STATUS Status; + EFI_STATUS Status; + UINTN NumberOfBytes; + VOID *Mapping; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + + NumberOfBytes = Size; + Status = mIoMmuProtocol->Map ( + mIoMmuProtocol, + (IsWrite ? + EdkiiIoMmuOperationBusMasterRead64 : + EdkiiIoMmuOperationBusMasterWrite64), + HostAddress, + &NumberOfBytes, + &PhysicalAddress, + &Mapping + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, + "%a:%a failed to Map() Address 0x%Lx Size 0x%Lx\n", gEfiCallerBaseName, + __FUNCTION__, (UINT64) HostAddress, (UINT64)Size)); + ASSERT (FALSE); + CpuDeadLoop (); + } + + if (NumberOfBytes < Size) { + mIoMmuProtocol->Unmap (mIoMmuProtocol, Mapping); + DEBUG ((DEBUG_ERROR, + "%a:%a failed to Map() - requested 0x%x got 0x%Lx\n", gEfiCallerBaseName, + __FUNCTION__, Size, (UINT64)NumberOfBytes)); + ASSERT (FALSE); + CpuDeadLoop (); + } + + *DeviceAddress = PhysicalAddress; + *MapInfo = Mapping; +} - ASSERT (mIoMmuProtocol != NULL); +STATIC +VOID +UnmapFwCfgDmaDataBuffer ( + IN VOID *Mapping + ) +{ + EFI_STATUS Status; - Status = mIoMmuProtocol->FreeBuffer ( - mIoMmuProtocol, - NumPages, - Buffer - ); + Status = mIoMmuProtocol->Unmap (mIoMmuProtocol, Mapping); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, - "%a:%a failed to free buffer 0x%Lx pages %u\n", gEfiCallerBaseName, - __FUNCTION__, (UINT64)(UINTN)Buffer, NumPages)); + "%a:%a failed to UnMap() Mapping 0x%Lx\n", gEfiCallerBaseName, + __FUNCTION__, (UINT64)Mapping)); ASSERT (FALSE); CpuDeadLoop (); } +} + +/** + Transfer an array of bytes, or skip a number of bytes, using the DMA + interface. + + @param[in] Size Size in bytes to transfer or skip. + + @param[in,out] Buffer Buffer to read data into or write data from. Ignored, + and may be NULL, if Size is zero, or Control is + FW_CFG_DMA_CTL_SKIP. + + @param[in] Control One of the following: + FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer. + FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer. + FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg. +**/ +VOID +InternalQemuFwCfgDmaBytes ( + IN UINT32 Size, + IN OUT VOID *Buffer OPTIONAL, + IN UINT32 Control + ) +{ + volatile FW_CFG_DMA_ACCESS LocalAccess; + volatile FW_CFG_DMA_ACCESS *Access; + UINT32 AccessHigh, AccessLow; + UINT32 Status; + VOID *AccessMapping, *DataMapping; + VOID *DataBuffer; + + ASSERT (Control == FW_CFG_DMA_CTL_WRITE || Control == FW_CFG_DMA_CTL_READ || + Control == FW_CFG_DMA_CTL_SKIP); + + if (Size == 0) { + return; + } + + Access = &LocalAccess; + AccessMapping = NULL; + DataMapping = NULL; + DataBuffer = Buffer; + + // + // When SEV is enabled, map Buffer to DMA address before issuing the DMA + // request + // + if (MemEncryptSevIsEnabled ()) { + VOID *AccessBuffer; + EFI_PHYSICAL_ADDRESS DataBufferAddress; + + // + // Allocate DMA Access buffer + // + AllocFwCfgDmaAccessBuffer (&AccessBuffer, &AccessMapping); + + Access = AccessBuffer; + + // + // Map actual data buffer + // + if (Control != FW_CFG_DMA_CTL_SKIP) { + MapFwCfgDmaDataBuffer ( + Control == FW_CFG_DMA_CTL_WRITE, + Buffer, + Size, + &DataBufferAddress, + &DataMapping + ); + + DataBuffer = (VOID *) (UINTN) DataBufferAddress; + } + } - DEBUG ((DEBUG_VERBOSE, - "%a:%a buffer 0x%Lx Pages %u\n", gEfiCallerBaseName,__FUNCTION__, - (UINT64)(UINTN)Buffer, NumPages)); + Access->Control = SwapBytes32 (Control); + Access->Length = SwapBytes32 (Size); + Access->Address = SwapBytes64 ((UINTN)DataBuffer); + + // + // Delimit the transfer from (a) modifications to Access, (b) in case of a + // write, from writes to Buffer by the caller. + // + MemoryFence (); + + // + // Start the transfer. + // + AccessHigh = (UINT32)RShiftU64 ((UINTN)Access, 32); + AccessLow = (UINT32)(UINTN)Access; + IoWrite32 (FW_CFG_IO_DMA_ADDRESS, SwapBytes32 (AccessHigh)); + IoWrite32 (FW_CFG_IO_DMA_ADDRESS + 4, SwapBytes32 (AccessLow)); + + // + // Don't look at Access.Control before starting the transfer. + // + MemoryFence (); + + // + // Wait for the transfer to complete. + // + do { + Status = SwapBytes32 (Access->Control); + ASSERT ((Status & FW_CFG_DMA_CTL_ERROR) == 0); + } while (Status != 0); + + // + // After a read, the caller will want to use Buffer. + // + MemoryFence (); + + // + // If Access buffer was dynamically allocated then free it. + // + if (AccessMapping) { + FreeFwCfgDmaAccessBuffer ((VOID *)Access, AccessMapping); + } + + // + // If DataBuffer was mapped then unmap it. + // + if (DataMapping) { + UnmapFwCfgDmaDataBuffer (DataMapping); + } } diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c index d3bf75498d60..7f42f38d1c05 100644 --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c @@ -45,136 +45,6 @@ QemuFwCfgSelectItem ( IoWrite16 (FW_CFG_IO_SELECTOR, (UINT16)(UINTN) QemuFwCfgItem); } - -/** - Transfer an array of bytes, or skip a number of bytes, using the DMA - interface. - - @param[in] Size Size in bytes to transfer or skip. - - @param[in,out] Buffer Buffer to read data into or write data from. Ignored, - and may be NULL, if Size is zero, or Control is - FW_CFG_DMA_CTL_SKIP. - - @param[in] Control One of the following: - FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer. - FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer. - FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg. -**/ -VOID -InternalQemuFwCfgDmaBytes ( - IN UINT32 Size, - IN OUT VOID *Buffer OPTIONAL, - IN UINT32 Control - ) -{ - volatile FW_CFG_DMA_ACCESS LocalAccess; - volatile FW_CFG_DMA_ACCESS *Access; - UINT32 AccessHigh, AccessLow; - UINT32 Status; - UINT32 NumPages; - VOID *DmaBuffer, *BounceBuffer; - - ASSERT (Control == FW_CFG_DMA_CTL_WRITE || Control == FW_CFG_DMA_CTL_READ || - Control == FW_CFG_DMA_CTL_SKIP); - - if (Size == 0) { - return; - } - - // - // set NumPages to suppress incorrect compiler/analyzer warnings - // - NumPages = 0; - - // - // When SEV is enabled then allocate DMA bounce buffer - // - if (InternalQemuFwCfgSevIsEnabled ()) { - UINTN TotalSize; - - TotalSize = sizeof (*Access); - // - // Skip operation does not need buffer - // - if (Control != FW_CFG_DMA_CTL_SKIP) { - TotalSize += Size; - } - - // - // Allocate SEV DMA buffer - // - NumPages = (UINT32)EFI_SIZE_TO_PAGES (TotalSize); - InternalQemuFwCfgSevDmaAllocateBuffer (&BounceBuffer, NumPages); - - Access = BounceBuffer; - DmaBuffer = (UINT8*)BounceBuffer + sizeof (*Access); - - // - // Decrypt data from encrypted guest buffer into DMA buffer - // - if (Control == FW_CFG_DMA_CTL_WRITE) { - CopyMem (DmaBuffer, Buffer, Size); - } - } else { - Access = &LocalAccess; - DmaBuffer = Buffer; - BounceBuffer = NULL; - } - - Access->Control = SwapBytes32 (Control); - Access->Length = SwapBytes32 (Size); - Access->Address = SwapBytes64 ((UINTN)DmaBuffer); - - // - // Delimit the transfer from (a) modifications to Access, (b) in case of a - // write, from writes to Buffer by the caller. - // - MemoryFence (); - - // - // Start the transfer. - // - AccessHigh = (UINT32)RShiftU64 ((UINTN)Access, 32); - AccessLow = (UINT32)(UINTN)Access; - IoWrite32 (FW_CFG_IO_DMA_ADDRESS, SwapBytes32 (AccessHigh)); - IoWrite32 (FW_CFG_IO_DMA_ADDRESS + 4, SwapBytes32 (AccessLow)); - - // - // Don't look at Access.Control before starting the transfer. - // - MemoryFence (); - - // - // Wait for the transfer to complete. - // - do { - Status = SwapBytes32 (Access->Control); - ASSERT ((Status & FW_CFG_DMA_CTL_ERROR) == 0); - } while (Status != 0); - - // - // After a read, the caller will want to use Buffer. - // - MemoryFence (); - - // - // If Bounce buffer was allocated then copy the data into guest buffer and - // free the bounce buffer - // - if (BounceBuffer != NULL) { - // - // Encrypt the data from DMA buffer into guest buffer - // - if (Control == FW_CFG_DMA_CTL_READ) { - CopyMem (Buffer, DmaBuffer, Size); - } - - InternalQemuFwCfgSevDmaFreeBuffer (BounceBuffer, NumPages); - } -} - - /** Reads firmware configuration bytes into a buffer diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c index 40f89c3b53e2..471ab0335e64 100644 --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c @@ -16,6 +16,7 @@ **/ #include +#include #include #include #include @@ -85,7 +86,7 @@ QemuFwCfgInitialize ( // (which need to allocate dynamic memory and allocating a PAGE size'd // buffer can be challenge in PEI phase) // - if (InternalQemuFwCfgSevIsEnabled ()) { + if (MemEncryptSevIsEnabled ()) { DEBUG ((DEBUG_INFO, "SEV: QemuFwCfg fallback to IO Port interface.\n")); } else { mQemuFwCfgDmaSupported = TRUE; @@ -129,56 +130,78 @@ InternalQemuFwCfgDmaIsAvailable ( } /** + Transfer an array of bytes, or skip a number of bytes, using the DMA + interface. - Returns a boolean indicating whether SEV is enabled + @param[in] Size Size in bytes to transfer or skip. - @retval TRUE SEV is enabled - @retval FALSE SEV is disabled + @param[in,out] Buffer Buffer to read data into or write data from. Ignored, + and may be NULL, if Size is zero, or Control is + FW_CFG_DMA_CTL_SKIP. + + @param[in] Control One of the following: + FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer. + FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer. + FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg. **/ -BOOLEAN -InternalQemuFwCfgSevIsEnabled ( - VOID +VOID +InternalQemuFwCfgDmaBytes ( + IN UINT32 Size, + IN OUT VOID *Buffer OPTIONAL, + IN UINT32 Control ) { - return MemEncryptSevIsEnabled (); -} + volatile FW_CFG_DMA_ACCESS Access; + UINT32 AccessHigh, AccessLow; + UINT32 Status; -/** - Allocate a bounce buffer for SEV DMA. + ASSERT (Control == FW_CFG_DMA_CTL_WRITE || Control == FW_CFG_DMA_CTL_READ || + Control == FW_CFG_DMA_CTL_SKIP); - @param[in] NumPage Number of pages. - @param[out] Buffer Allocated DMA Buffer pointer + if (Size == 0) { + return; + } -**/ -VOID -InternalQemuFwCfgSevDmaAllocateBuffer ( - OUT VOID **Buffer, - IN UINT32 NumPages - ) -{ // - // We should never reach here + // SEV does not support DMA operations in PEI stage, we should + // not have reached here. // - ASSERT (FALSE); - CpuDeadLoop (); -} + ASSERT (!MemEncryptSevIsEnabled ()); -/** - Free the DMA buffer allocated using InternalQemuFwCfgSevDmaAllocateBuffer + Access.Control = SwapBytes32 (Control); + Access.Length = SwapBytes32 (Size); + Access.Address = SwapBytes64 ((UINTN)Buffer); - @param[in] NumPage Number of pages. - @param[in] Buffer DMA Buffer pointer + // + // Delimit the transfer from (a) modifications to Access, (b) in case of a + // write, from writes to Buffer by the caller. + // + MemoryFence (); -**/ -VOID -InternalQemuFwCfgSevDmaFreeBuffer ( - IN VOID *Buffer, - IN UINT32 NumPages - ) -{ // - // We should never reach here + // Start the transfer. + // + AccessHigh = (UINT32)RShiftU64 ((UINTN)&Access, 32); + AccessLow = (UINT32)(UINTN)&Access; + IoWrite32 (FW_CFG_IO_DMA_ADDRESS, SwapBytes32 (AccessHigh)); + IoWrite32 (FW_CFG_IO_DMA_ADDRESS + 4, SwapBytes32 (AccessLow)); + + // + // Don't look at Access.Control before starting the transfer. + // + MemoryFence (); + + // + // Wait for the transfer to complete. + // + do { + Status = SwapBytes32 (Access.Control); + ASSERT ((Status & FW_CFG_DMA_CTL_ERROR) == 0); + } while (Status != 0); + + // + // After a read, the caller will want to use Buffer. // - ASSERT (FALSE); - CpuDeadLoop (); + MemoryFence (); } + diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c index 071b8d9b91d4..1eadba99e1b3 100644 --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c @@ -17,6 +17,7 @@ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ +#include #include #include @@ -97,57 +98,30 @@ InternalQemuFwCfgDmaIsAvailable ( } /** + Transfer an array of bytes, or skip a number of bytes, using the DMA + interface. - Returns a boolean indicating whether SEV is enabled + @param[in] Size Size in bytes to transfer or skip. - @retval TRUE SEV is enabled - @retval FALSE SEV is disabled -**/ -BOOLEAN -InternalQemuFwCfgSevIsEnabled ( - VOID - ) -{ - // - // DMA is not supported in SEC phase hence SEV support is irrelevant - // - return FALSE; -} - -/** - Allocate a bounce buffer for SEV DMA. - - @param[in] NumPage Number of pages. - @param[out] Buffer Allocated DMA Buffer pointer - -**/ -VOID -InternalQemuFwCfgSevDmaAllocateBuffer ( - OUT VOID **Buffer, - IN UINT32 NumPages - ) -{ - // - // We should never reach here - // - ASSERT (FALSE); -} - -/** - Free the DMA buffer allocated using InternalQemuFwCfgSevDmaAllocateBuffer - - @param[in] NumPage Number of pages. - @param[in] Buffer DMA Buffer pointer + @param[in,out] Buffer Buffer to read data into or write data from. Ignored, + and may be NULL, if Size is zero, or Control is + FW_CFG_DMA_CTL_SKIP. + @param[in] Control One of the following: + FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer. + FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer. + FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg. **/ VOID -InternalQemuFwCfgSevDmaFreeBuffer ( - IN VOID *Buffer, - IN UINT32 NumPages +InternalQemuFwCfgDmaBytes ( + IN UINT32 Size, + IN OUT VOID *Buffer OPTIONAL, + IN UINT32 Control ) { // // We should never reach here // ASSERT (FALSE); + CpuDeadLoop (); } -- 2.7.4