From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from NAM01-SN1-obe.outbound.protection.outlook.com (mail-sn1nam01on0064.outbound.protection.outlook.com [104.47.32.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id F15E221CC5369 for ; Thu, 6 Jul 2017 07:28:30 -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=mQ2b+1YdQAtY6pArqUVjkok/Tq684neoT8jH5Mraf1k=; b=vjFo6goWj8MNqc+XBk2wgOTcEyM+0r45SGRCCySGNAOkXpcY1DXHtTyMdKTOJus4x4tTVh/twDWFenbU1VSW+A7YkCfljgZ8FfopPzAYf7964+c+Y3GqNfh1kEx/Hv/UStfY7T9LFxe4EmUXxEz1MDLkyRM0TdQ/pcmp86XlZVk= Authentication-Results: lists.01.org; dkim=none (message not signed) header.d=none;lists.01.org; dmarc=none action=none header.from=amd.com; Received: from brijesh-build-machine.amd.com (165.204.77.1) by BY2PR12MB0147.namprd12.prod.outlook.com (10.162.82.20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1240.13; Thu, 6 Jul 2017 14:30:09 +0000 From: Brijesh Singh To: edk2-devel@lists.01.org Cc: Thomas.Lendacky@amd.com, lersek@redhat.com, jordan.l.justen@intel.com, leo.duran@amd.com, Brijesh Singh Date: Thu, 6 Jul 2017 10:29:41 -0400 Message-Id: <1499351394-1175-4-git-send-email-brijesh.singh@amd.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1499351394-1175-1-git-send-email-brijesh.singh@amd.com> References: <1499351394-1175-1-git-send-email-brijesh.singh@amd.com> MIME-Version: 1.0 X-Originating-IP: [165.204.77.1] X-ClientProxiedBy: DM5PR15CA0024.namprd15.prod.outlook.com (10.173.207.162) To BY2PR12MB0147.namprd12.prod.outlook.com (10.162.82.20) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: a52e83e5-d7ad-4c08-816e-08d4c47b815f X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(300000500095)(300135000095)(300000501095)(300135300095)(22001)(300000502095)(300135100095)(48565401081)(300000503095)(300135400095)(201703131423075)(201703031133081)(300000504095)(300135200095)(300000505095)(300135600095)(300000506095)(300135500095); SRVR:BY2PR12MB0147; X-Microsoft-Exchange-Diagnostics: 1; BY2PR12MB0147; 3:qyvC/uafG8AJFpmt8WgH1Ev2QoCq7CXynJJTHA+1CTU8GqSvGCH0o1dxyOQq51LwAVZEq7c0WMenPrIa2XNMOi26ZnMvcuQKqawMc9i24qYR8gv828pE/WcOgptKPXphtZBJ0D0qftjRqoXuzx5OY/Gzu4EPnICNcgZ1q03wHwDB8aDab1g7Ciq+xfq5o+adKqgouTkatTrtewPy+u1jvt5V/+QAlM6Pv38/gV+ILRUmp5J8yhb134+FohCRR9TyJpjK1m7ueuvBYC5q9hH9Vn9NNri5tD3VOMCoMeOww4b3NXoF/WVafYtrY5Udh30XcSijI1SH6H4tHmcA+8EpDjDAhCy4sDqu7iTu3qe0W6jRE4BmkgQH7+uJWpRvDjh8sMsk2ZI3jX7uqeaq/04lMqO4uxnMRgvRceyMvm6N7XEwztbyiCP5fwWG7RX3xx870qJZTKd13E3ru7B+trbULQvtzNF15vjwyQuHzQlyE881m67SGoRFu7ZfT70R6ynyF3saDtGO9+YT4MTmZ7c5CnKreXc05MoEk5cneJ9pfAzU9mylQKM3xTyj+zEcfhZE9RQ98kqmVN6pM2PT+uKflBvEMr/P9b5IYAGqj3jIcI5CEj8Pw2lSsnZyPGU5sN37aSitXHd6tvi4/89KRRoiOIPEVhrTXP3A9ou+pF4hytPlU6GNNM04TRPfsHZ3PkSPVAA9HXuRb0J9JFpcApUgRJJlimNvuZ0vP6UJ+I5NSJdlEQ8cqY1HULdyIvTXaxIcicNvKZwH2m/a7dzjOE1WlQ== X-MS-TrafficTypeDiagnostic: BY2PR12MB0147: X-Microsoft-Exchange-Diagnostics: 1; BY2PR12MB0147; 25:C2LlZN/5rh9eZIheRQYPzj8ab8W0E8oLuFdux1n+fbGTw5vES/kejK+NjqQvWx5390yf2rD5f9tRSGWQrblnZSbCl/VmOJVfjKCdGSt51woLnoHlOr4D5SRhIcB9Jb9MTuflQ+ehk3IuzJeV1kbrltznnublKDORwkQ0kQynbk4c20qmSUv/7LH7ugxRBDkAIQ6cflVgV9qpfSfyn7nA/QE9Oga8WciwonXk73WT6Gk3KJfkn4/BAbHIooGo2Np+vpgPZxRHXETbNvRgVlBCcTygjKwxsdE5uf4FKblllJfHsu3cvnJc94vVeD2oFv3nOplrwjnistIQqx8XxmnOADiQatMvHTllqfhSKp1mHRfOlHaT0Hm7FZVMpkDZLNo74c/6P/y8Jec4+N3LVg8pnPJjch0+xmybyF//45MVQShGaB0aun/kA9++GoRjSjHIMiRn76Gk263OTF3chU3wmETDTIjaGDvFyQh1+QgTlXwwD+QD3ru2Fd9W71R8PdqsHsQzvIU0rGKvsUn1F9AbZbC9qYQS1hQSlnBtfx5TvUL1JSfWVEt+ensHIVEAAgk4iTmCkf5sNpLnHQMwfdGpeKNYGrXY8eZTKIhTov1JneYomXgx2ABuLZMMbQj06D4o0yJagicskPWuZLPj78riAyExdz8ONKB6Sbl7k4pWa1w7ROLq2IOpbZtZ/f5G9pN/Vtw+bUwWAjC0NpA95mc+0P/tom9Fxe6Jwyz5NPD/1iUeR1UIE3DFFFIPRsC6FUK62xf6remAsZfE2WodjwTXmhfhJd5PmfirDf2iK1KmrMLEdNRurfh3XYBrcZE24rV1RTfLFqVbEJIRRCE0hrYKDkWdBw6EmxoQ5ZSmVJjR3LHXhfE28l+ymAxjyxoJ0uXyn5fQlM8Gml1/tK26tLBzb9jGMyoCzYr7Eh693jjRXio= X-Microsoft-Exchange-Diagnostics: 1; BY2PR12MB0147; 31:oatL83gNRbGMnktW5KffbWLkjMpDjQ3GTm/hoB3EYr5IhMGllfT3cgphtl9ujxg3+AURSD271Gr3K0mV0Kw/LJwxikFPHqHHe6ipmsCljrihHWYzAG5eqcikHsO6jW7EDrliWXanNHEqx5fdbTrmsSSXia3RXGBvfN/F2hzkqjk1c1KPShUhaWAfQPlE4CFoDLS+bN/+1X48tWzCoqcsuf2ZQcw20dWnhHk0OLOmf7osNip5zvlSZkgFvH5GyYwCAki5IiURqk+4jD5fyJ5cviZNy+Nc4tZ4yNPLEWXNFaXxjCHNae5NKDviYcNU+a4uvAz96fW6JsNCOCCsffqEmvMfkF09SGOnNgylaZCgbEwkdNOx2NjLpx6sDfqTsg9v+e6MzuvnMwZc/TPNrisEMvBNCtsyQKvSZdFNrvX7BePYZ3d3uRy4Ned80+Mjzxd9bayV2cLWzPIUOwI9UumyyVmNUZWEt+R8+SAQjKIWPZF1JXzxOpyzQh/4a9fAKbgLunpMhD7cKBm7t8iaJhRuCCmw3qqYwVBpX0e1wRL7redf4QnQ95YO/etmmaHBI6vQndpmv+M2N2xAPs5pBDcBrDn3e+SxfBp/ZAEYd7htkQZ3+1l4MyRjUtTkKEezQD4EuEBtUusODZsT82mxQ5JXEs1XwOKGmZv/L1LNwZxepBs= X-Microsoft-Exchange-Diagnostics: 1; BY2PR12MB0147; 20:hfL1wgiJ/+bkDpQBb8I7NxcU4LTj7Klg/s4C/0lZT2hzDOeWJvT1nDo4NhCRnkCwf0g5jAlcTMHmikN0gfoK3OElHbnkRA2FmGpS3wYgb3doQmVnWZDht0wq1mGBzVRCWWm5t4vclMlLhzjcwUYoDQZ31dXGqjkaEznW+FUT11inPIfhq6wIJCqtJ19N4B+0J7szn01RbuE2weVa6izDNPHMXiCTIW2tltQkIiA1i71d7sCgnag6zUb5gtj4pfA+eQ5oNNffy3tZbBqsoyVqbecB3XGvlxM2PuieaV9Y2SBkym8JxkNBQHIJ5qrPQuTmavPPcI7u6wEeqy/+/yrcNycTvPNw6bD5ekmIyjc2hVB/QNs0CSGW9Xd7sM1MOR4eCE7UqnADy/fAS7HOJdriV1bCydpFtcIDSIoI2EtVZ0yqdA8XCfgpjTSnvdxVFA0C2l39a+ayoyWFnNr1hkQF2i1F7I5f45nJla8W43g4ycN7hLVGB71MbnaNzsTbW7Y9 X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(125551606395959)(236129657087228)(767451399110)(148574349560750)(167848164394848)(158140799945019)(228905959029699)(247924648384137); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(601004)(2401047)(2017060910048)(5005006)(8121501046)(93006095)(93001095)(10201501046)(100000703101)(100105400095)(3002001)(6055026)(6041248)(20161123560025)(20161123564025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123562025)(20161123558100)(20161123555025)(6072148)(100000704101)(100105200095)(100000705101)(100105500095); SRVR:BY2PR12MB0147; BCL:0; PCL:0; RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095); SRVR:BY2PR12MB0147; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BY2PR12MB0147; 4:DFtSvveDAd0b25kHyf7y3TklFPHhcIRt7GPFm322qD?= =?us-ascii?Q?wzoI45eF0CgRqJ2HpPxGgpjDneRXN9MtRW36LJUzorrmd57zm7U0bEsShANJ?= =?us-ascii?Q?lbxjgbYUPsPNfIwI/XYu/x7TqXglC2UNGAlZQnVzwfixnWCc7WgsGIOKgOom?= =?us-ascii?Q?YrkEMKWY+nR+y1FtR9fcrAu5DPGwh+fbaq1jneoTzzKLzeejUr5yW5gfQrvY?= =?us-ascii?Q?lFi9hTAAzLuwn84wHuQJB+3eHVBoU5GJ7nsYwPSZmgUz/MEJbtSPlgk4Sqhv?= =?us-ascii?Q?EBRw72UosmAmifDRPdqrqN0DMdF3VULvCeHOWKc4V7wuguNguVBP7UNynm27?= =?us-ascii?Q?siqiRwmZJ88Z2Lkazs9io8mqfhGLY53chTDcYvHGwuvKbtm3UmPjtVRSxg0v?= =?us-ascii?Q?wZmQr5g25HADag9bJWKVOdOlxfbtcofIrazE6M2z1eKKy5mVEv4yiORKylwM?= =?us-ascii?Q?viFJmYlvcgEonugmZbQJEWl3tMgR1y+GbMazDreaFJ+WlpET23hAiR6J0pTv?= =?us-ascii?Q?smLYzt7r73NI85E0rlsTlAxgoQsb9OaFmSvviNHxMu3MCRVUy513StXJyeT7?= =?us-ascii?Q?/BY1aUh9nKhVqsA+U2yehRG2PChyhRt6C540JC+CXFLA6oS+OuIp2ExhZl/O?= =?us-ascii?Q?8LttlZyxSNInlIbl6ooQJpjF59LFYR+c50WJofOCH9SWE/vWKj85NdmbQoY7?= =?us-ascii?Q?o5p1y508dFbILUjVS1KvN3uf36mC7lRMBYQ4IKAidxAKeDuigKKUd4ZqGGIr?= =?us-ascii?Q?OtMiuMsBE4h6msrDnJDDplBijuoainspVyheJUkCnDsrNva2LLjcFqLByOZB?= =?us-ascii?Q?tcUR3JAFtBQ0suHdsJD+fqBGBx7mNzLDv2y+7IYHU6g8WwrGzya2q64BAq6N?= =?us-ascii?Q?dxmOwO9gZLoMViFGsKJ7kIF4UZAdml4QkWmHrEPn4Wxx0d0+G4Zkvf8b9uZK?= =?us-ascii?Q?Wp8ps5f/+gL/rjVNJPt0B6WaiVlghV+E6BAAJ8S16iOk5BeLkGk8pFhzO5ON?= =?us-ascii?Q?OQvbxzzf0tt0O5FzbXD62vi3A3go1Bv2W0pw4K9T6OoS85nCqXML/6WZL+/s?= =?us-ascii?Q?bE76FK44lUOW0saQ3R4BdBVn+bH+9xlH/J6CTtBfVO0QzNZPctU4XqRGXgEo?= =?us-ascii?Q?IXMSkOlrT2TDvqXsbN4A5wm0IK/ABj80D8ZnMDNHm2g42EWjQYQF7Uofih6a?= =?us-ascii?Q?UaSLIX/MejdxeobJfJdQROaMV3Si1r1XzJMsnW3kD+evLGABMeq42PYiIIG3?= =?us-ascii?Q?VL8tC3giuwUcfEhuMuLQYeGOFI7EwJA2FBYCE/a/VWIDB6R7R8pyPM10coVm?= =?us-ascii?Q?LJoSz9rqhqoFVkshKOmY828HBIt4JRHCzWp9V+fbxBe14SOodKz9m1bTE3PI?= =?us-ascii?Q?aI7OxnXmPcQYuCstAypufzuN3x9XxRzY9yRMtetMAhTEQnmLI7iqBovQUPeq?= =?us-ascii?Q?jkC2Xa8pIkovLfs2NB9/KY2a7BYonjxWCCgT8+jpOCU75bB39EMvVqMANt+Y?= =?us-ascii?Q?mVb2d//QUWMA=3D=3D?= X-Forefront-PRVS: 03607C04F0 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(4630300001)(6009001)(39450400003)(39850400002)(39840400002)(39860400002)(39410400002)(39400400002)(53936002)(48376002)(305945005)(2351001)(5003940100001)(2361001)(7736002)(50986999)(76176999)(5660300001)(4326008)(42186005)(16799955002)(2906002)(66066001)(6116002)(3846002)(15188155005)(47776003)(53416004)(6486002)(38730400002)(33646002)(81166006)(36756003)(189998001)(53376002)(110136004)(25786009)(50226002)(8676002)(6306002)(50466002)(86362001)(6666003)(966005)(2950100002)(53946003)(478600001)(6916009)(579004)(19627235001); DIR:OUT; SFP:1101; SCL:1; SRVR:BY2PR12MB0147; H:brijesh-build-machine.amd.com; FPR:; SPF:None; MLV:sfv; LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BY2PR12MB0147; 23:aExwNQzXxteOG2Ft5nLeHVbpppSfHF5YwrLrXgz6G?= =?us-ascii?Q?fxJijQKkLcEHm8Hsa6mWKlRC5FZVbkCzYHe/qxIT4EM73GnUc8NxdOlHHxLi?= =?us-ascii?Q?tVeOT9flNV5Iz0j27lsheHxIb0tGl01Iiqy01pcrZSV1yzcU4VB9EVClZW42?= =?us-ascii?Q?qCMe4C3gXlLmyhLqcv1A6qhE9PnIbHJ1V5XKzAkime4yKzSxp6b1HKItIoT9?= =?us-ascii?Q?bQSduIzHLKxKrYAGgwmeEKDJ2Ho/onka8Egl4sZz5k+ghM4tKMcbcQJhbkUa?= =?us-ascii?Q?2HD/mut6qwh+p2tYD3ZvpJLmEcJw52ggasTNgMqX4T52fX9aAB6wq72yaF/r?= =?us-ascii?Q?s6NuJjtpURUvG5EhaSBa8joIEMFfASy8ofYiazeBQxmWpyR7QqrCMQEu4VGo?= =?us-ascii?Q?+d1lgaXZVJ3bseeCPHh9igE//dyIbXPv7HV5hiccPFtraIZWraoUdYZ3kwXg?= =?us-ascii?Q?sELQOSmGZELsfUYvr6AOH/P8ftxmxfI4Sw3I9xZToEW9Es6+SA1cEykiEqPI?= =?us-ascii?Q?M7a7K3RKBDRkeIVAU002+o/0uIzJesb92vbxpLyCrCKYEPeSeB3JRsuQetWC?= =?us-ascii?Q?P4BRZUp86Hxgh171uadDzTD5epRuJL9Kkee9KAcw3zHhgicfteS3gFb1jl5+?= =?us-ascii?Q?GYzrhz6vQcbkfgSN6qVfrCW0kqGHShHtnpolC7LG+kYua7WwXaHVxoIeZ0kF?= =?us-ascii?Q?z6PgV1WykV1MHF0F8drY+u/EcIJKjtZMhBTaoh50KjfkSw9ZsyEw+abLHf3a?= =?us-ascii?Q?OsTbrpXRoc+caVa6X41otKDXSaLIivF+3Hc38YIS2Bc6H8CS4vUwnQwwYX34?= =?us-ascii?Q?n03XqlnXxLR8IlI//cCiS18slv0Iw/ls4cdsHWiA37U2qe9GsZEJxzqZDbav?= =?us-ascii?Q?NZKWaMm8NQQnuDwdIAwgUvVmf+lXcp7t0D96K9rrvZPWYfWYkwGSaAQ1xZZg?= =?us-ascii?Q?4sUBAsFcX/hdybDioFGOEjafKQ1+152jPPqkeIyj5nhWRRO7FnHV6ayWuGjE?= =?us-ascii?Q?gztHNe00qgfD9On68uEzmRsX6Q8DGq1XDRu975uVCrIS19NbNikJsA372chy?= =?us-ascii?Q?JAG7w2egPZ1YcTjD8UTIDUDS0B0H2oKknPSOCg7KhO9bEqqQ24NioKM5vb1x?= =?us-ascii?Q?fFILe4J1wtjZS1qlYFevfA9LlD6eXbJU/U/gWg/IR+RKUEAjzvDboXO3rLW3?= =?us-ascii?Q?j39IAUU/B3N65ZD7Vva83N9zZrlt/kW+z1Jl7Ep6Di16p4fsETvfHv5lDv1u?= =?us-ascii?Q?awtPpbJBkq1ibYhMXI=3D?= X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BY2PR12MB0147; 6:ORU9MXw6+bZI+h2OJvVLAmGUAjsdu13uxJGg+4QRIp?= =?us-ascii?Q?EvEExAntwMpOCc2RzfZLBfTnQ2fHG2+eK1WA9VbxSjaDrf+EkbkuvT6jqLv1?= =?us-ascii?Q?tD7xAJkMVeE2H8ehr0TUB83g45BwfzbNQNzSUclGSGpXxKrFB+0L3yr5HcIX?= =?us-ascii?Q?jNtEX8PmpZDJHLEqkadP0yxUeF0wWggCwDxcWS5i0A9EcSIl9S2PSVQkG1Yp?= =?us-ascii?Q?4x110pm4aSEwMR8wqotgQCW+FlujdjiZT9+irGzURcSeasBPqb0UyHGK/tBo?= =?us-ascii?Q?/Q2xCPxLm0tVEJtc8m06cCztwoCnvf+g8dySmVaDNdnDBwJyVLFFrbM+y+ft?= =?us-ascii?Q?UZSfWBN7aGO+Ipc+iMwPl4E7fBey0RFEC87nahV+gOKgF433P5fBmEWrkpWX?= =?us-ascii?Q?0KwhKUyyIQSHcKM7j3ag1HQ0ETnvs2gvHV4OdCod0nPhZWKVW8MNcF0Fp+tj?= =?us-ascii?Q?ZmlSqTeeQjHmC0g3Ej9+v8rqw/q3JE7iCM0ARYusH2jKVwzVAcnQjI5nU1IR?= =?us-ascii?Q?dU7iClQrZAHzmtvN6v282NDSRHDYzg0EsTddxC6vF8Br+rK8YmgNGaKCBxER?= =?us-ascii?Q?XW0yTWFkJXRDNBCx9ppSJ+8PmW3QFrSyIfNhzQTsWnEXzc0eeRGa8HKjoIgq?= =?us-ascii?Q?fTqZqbZfVle6NGjzLY1pUsHrSLxQhEpp8eS2ygHUPwAYTNPNgwVDnKrpr8yc?= =?us-ascii?Q?/MaGoGAni0LanMfFfUS68fueVJXoovOVphGDdayCF+oSQaAWiCMD0ZLSVfGy?= =?us-ascii?Q?1PVt1bSieva3nZ6ixWnwU9nWEcJTm6G/mOUljVo9c1khNjLY9X3oK1n67sbI?= =?us-ascii?Q?oV8Tb8Zf6fT1by6ZTcL2hgX8nvzY7/yAnb/ePVLg6N7NU3PDwHIGXfFw84oN?= =?us-ascii?Q?1UVozR6EbaRUekcjk/ZftTG57ye5Na1O4B7yU3WzeoFZauat5GbgLWLxpOCE?= =?us-ascii?Q?+EZ0YROk3OjGbmreHwmUAkn7PIzrL99PL21j9F4wDLPymqEOLiPB0vs28HuX?= =?us-ascii?Q?rjf02IdKv7eaLziLwYnkn3?= X-Microsoft-Exchange-Diagnostics: 1; BY2PR12MB0147; 5:Riw1e0rbzuV3EnzNQc8ZR3cj2vdOST/LyFtru5wDU924Fb6V3PXxmEQOtRGsadhYjz9BGrNv7PY1tN/QrwelODy60ep0T/V38mwvToqchKj/dInRv7bHjwVvyDDUathU4uFNMJuQ0D3oKFTTI9DoT3XbprQL+xgzexEXEYKJxClG2Mcde3XCBL0PS3KxA1mIdN2AsrYX/Cfi0J7ZLxB1iWdLBNAk6XnGV4jUyWLmltm5qADSeCO9GgN7kzHoErfVewI1C7sIbf034nsBPW8SxyVOcpkKwdF/ZT0QZneGAUfTiQgel2h4YuMYVaa6XY6P3R563TB9GZqNyLqC4W/J2qTF5sI9UnykHkW9crAmOD0Y+3caCIcgCXKIk8cWH1Ba1RRTLdmbTiiszhl92Z22ka+207oxq4z4iE69ZeQXYlOCSXXfnaDQA3055ksLzr0Hku5oaMi3qTELxLONNsdQjPY5J2y8ICcDA847cAqvACJStVrprlKm4Z+qdKEEkQ4Y; 24:d8QonLk3GCT9/P7C/x65xoOiCIfn5/Fg/ncWv9qYPH0bH44F3sUWQjRNbNN28w1MSspplFpI5P/zmgIv+J8DliVajEht/pHyjetvOiXvUoU= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; BY2PR12MB0147; 7:nYyO9uEeqXnGJl/kLM4CooIUsRiHCmg0wR0b2Vvx+xl9vca0mMj2tUVYIXfahSkasVcXs2S41dFa+CxTG4Bai2PMH8+OiYS+nC+Fu3Pu05tCNiEuj16vHlBnrtipHCN0uXmInIjlufuBwZbiOd3IvEqxGexl0hcyyL8Gh7sj2QS0RYzrRFMF0a6VLeGiGr2EeqBRQQt4l2wHT3qFUziALVFSewyvrZ77GP2Xlay2toOYF+osB0eB35PEGqaDgBmAwQd12XLg4cZnmFaLzpMdgEkHz2jfcGOjw3RtZ2Ly8QgaLDSLFKgWlqjDB8tusQC424JWxSP1rPq2Om9cv3uegArAe5DuqdSe5Vd98d/ouT2GCkgCVVOrhgIveIp3MdSEnoZh4ElYBbKFpBbYaSg1KmRq2WDPoEys2UlEJ3QjcKONjRIXuq/dIrnS7EUh5ypQ3AFE1kTVQT5gB2JK8ASssdr5xYKL6CvLBE1IacOGq+8h5th82abMgIkfnFzYKyk3glSPAGH7woNK1zmCK4gh+aAG2pQwMsITc8yyiVveEUfl2STkhn2Bf1unn38JlV2UbDLm5/GvMHcUJ1BfbVD+7XIBkm5up14SNJFR53vMpvaDdLLkc735e6Ki5KNXLpHZPROS8t5sb+wFeJl1T4qRu3NZ24H4yCBHUa5NJyiKfLsjO0qdtEclO/mQHiwzys1JhaL8youGtEaCfsjTVENmxUCv+6vfCt+XO1HrKJeHknQeW2wM/draXkgWsdxsLTrjmX5qLD58NMLPCCH1rKn58pMhc0gutqGhpZpY83ISiG8= X-Microsoft-Exchange-Diagnostics: 1; BY2PR12MB0147; 20:VxegMl6N2FVZBpM7Hvid9sjRjKjPQWQ/voKgZS44HqIpOLmaB+O9tKf/HLVHDTK1l50ntxlddCDuRAFU9BXZ3CFH6t3gpksi6SxaekJ5YeEa153GCdxbISBw/hJRNnBXzqzShRap3Fp+l8qPH5TxAo1aygWVtc54W68+2CuxQSmFjl5eV4uZYhOtZqr46QUuuZyMUFke4WU5EG6LguffNUh0IeTEkcpzUrfirTfrCh5Z1tNawFX280cU+x04MpLM X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Jul 2017 14:30:09.1139 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY2PR12MB0147 Subject: [PATCH v8 03/16] OvmfPkg/BaseMemcryptSevLib: Add SEV helper library 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, 06 Jul 2017 14:28:31 -0000 Content-Type: text/plain Add Secure Encrypted Virtualization (SEV) helper library. The library provides the routines to: - set or clear memory encryption bit for a given memory region. - query whether SEV is enabled. Cc: Jordan Justen Cc: Laszlo Ersek Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brijesh Singh Reviewed-by: Laszlo Ersek --- OvmfPkg/OvmfPkgIa32.dsc | 1 + OvmfPkg/OvmfPkgIa32X64.dsc | 1 + OvmfPkg/OvmfPkgX64.dsc | 1 + OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf | 50 +++ OvmfPkg/Include/Library/MemEncryptSevLib.h | 81 ++++ OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h | 184 ++++++++ OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c | 84 ++++ OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.c | 90 ++++ OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c | 84 ++++ OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c | 439 ++++++++++++++++++++ 10 files changed, 1015 insertions(+) diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc index c276a2cde931..29884b77859c 100644 --- a/OvmfPkg/OvmfPkgIa32.dsc +++ b/OvmfPkg/OvmfPkgIa32.dsc @@ -145,6 +145,7 @@ [LibraryClasses] QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf + MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf !if $(SMM_REQUIRE) == FALSE LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf !endif diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index 7ec6687903c4..2b646e4a4969 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -150,6 +150,7 @@ [LibraryClasses] QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf + MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf !if $(SMM_REQUIRE) == FALSE LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf !endif diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 3b436223f5be..32386de9b428 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -150,6 +150,7 @@ [LibraryClasses] QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf + MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf !if $(SMM_REQUIRE) == FALSE LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf !endif diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf new file mode 100644 index 000000000000..3cfd80a28c1d --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf @@ -0,0 +1,50 @@ +## @file +# Library provides the helper functions for SEV guest +# +# Copyright (c) 2017 Advanced Micro Devices. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD +# License which accompanies this distribution. The full text of the license +# may be found at http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 1.25 + BASE_NAME = MemEncryptSevLib + FILE_GUID = c1594631-3888-4be4-949f-9c630dbc842b + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = MemEncryptSevLib|PEIM DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + OvmfPkg/OvmfPkg.dec + UefiCpuPkg/UefiCpuPkg.dec + +[Sources.X64] + MemEncryptSevLibInternal.c + X64/MemEncryptSevLib.c + X64/VirtualMemory.c + +[Sources.IA32] + MemEncryptSevLibInternal.c + Ia32/MemEncryptSevLib.c + +[LibraryClasses] + BaseLib + CpuLib + CacheMaintenanceLib + DebugLib + MemoryAllocationLib diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h new file mode 100644 index 000000000000..b6753762423e --- /dev/null +++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h @@ -0,0 +1,81 @@ +/** @file + + Define Secure Encrypted Virtualization (SEV) base library helper function + + Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _MEM_ENCRYPT_SEV_LIB_H_ +#define _MEM_ENCRYPT_SEV_LIB_H_ + +#include + +/** + Returns a boolean to indicate whether SEV is enabled + + @retval TRUE SEV is active + @retval FALSE SEV is not enabled + **/ +BOOLEAN +EFIAPI +MemEncryptSevIsEnabled ( + VOID + ); + +/** + This function clears memory encryption bit for the memory region specified + by BaseAddress and Number of pages from the current page table context. + + @param[in] BaseAddress The physical address that is the start address + of a memory region. + @param[in] NumberOfPages The number of pages from start memory region. + @param[in] Flush Flush the caches before clearing the bit + (mostly TRUE except MMIO addresses) + + @retval RETURN_SUCCESS The attributes were cleared for the memory region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Clearing memory encryption attribute is not + supported + **/ +RETURN_STATUS +EFIAPI +MemEncryptSevClearPageEncMask ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumberOfPages, + IN BOOLEAN CacheFlush + ); + +/** + This function sets memory encryption bit for the memory region specified by + BaseAddress and Number of pages from the current page table context. + + @param[in] BaseAddress The physical address that is the start address + of a memory region. + @param[in] NumberOfPages The number of pages from start memory region. + @param[in] Flush Flush the caches before clearing the bit + (mostly TRUE except MMIO addresses) + + @retval RETURN_SUCCESS The attributes were set for the memory region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Clearing memory encryption attribute is not + supported + **/ +RETURN_STATUS +EFIAPI +MemEncryptSevSetPageEncMask ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumberOfPages, + IN BOOLEAN CacheFlush + ); +#endif // _MEM_ENCRYPT_SEV_LIB_H_ diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h new file mode 100644 index 000000000000..70cd2187a326 --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h @@ -0,0 +1,184 @@ +/** @file + + Virtual Memory Management Services to set or clear the memory encryption bit + +Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Code is derived from MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h + +**/ + +#ifndef __VIRTUAL_MEMORY__ +#define __VIRTUAL_MEMORY__ + +#include +#include +#include +#include +#include + +#include +#define SYS_CODE64_SEL 0x38 + +#pragma pack(1) + +// +// Page-Map Level-4 Offset (PML4) and +// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB +// + +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Reserved:1; // Reserved + UINT64 MustBeZero:2; // Must Be Zero + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // No Execute bit + } Bits; + UINT64 Uint64; +} PAGE_MAP_AND_DIRECTORY_POINTER; + +// +// Page Table Entry 4KB +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 PAT:1; // + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + UINT64 Uint64; +} PAGE_TABLE_4K_ENTRY; + +// +// Page Table Entry 2MB +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 MustBe1:1; // Must be 1 + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system software + UINT64 PAT:1; // + UINT64 MustBeZero:8; // Must be zero; + UINT64 PageTableBaseAddress:31; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + UINT64 Uint64; +} PAGE_TABLE_ENTRY; + +// +// Page Table Entry 1GB +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 MustBe1:1; // Must be 1 + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system software + UINT64 PAT:1; // + UINT64 MustBeZero:17; // Must be zero; + UINT64 PageTableBaseAddress:22; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + UINT64 Uint64; +} PAGE_TABLE_1G_ENTRY; + +#pragma pack() + +#define IA32_PG_P BIT0 +#define IA32_PG_RW BIT1 + +#define PAGETABLE_ENTRY_MASK ((1UL << 9) - 1) +#define PML4_OFFSET(x) ( (x >> 39) & PAGETABLE_ENTRY_MASK) +#define PDP_OFFSET(x) ( (x >> 30) & PAGETABLE_ENTRY_MASK) +#define PDE_OFFSET(x) ( (x >> 21) & PAGETABLE_ENTRY_MASK) +#define PTE_OFFSET(x) ( (x >> 12) & PAGETABLE_ENTRY_MASK) +#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull + +/** + This function clears memory encryption bit for the memory region specified by PhysicalAddress + and length from the current page table context. + + @param[in] PhysicalAddress The physical address that is the start address of a memory region. + @param[in] Length The length of memory region + @param[in] Flush Flush the caches before applying the encryption mask + + @retval RETURN_SUCCESS The attributes were cleared for the memory region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Setting the memory encyrption attribute is not supported +**/ +RETURN_STATUS +EFIAPI +InternalMemEncryptSevSetMemoryDecrypted ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS PhysicalAddress, + IN UINT64 Length, + IN BOOLEAN CacheFlush + ); + +/** + This function sets memory encryption bit for the memory region specified by + PhysicalAddress and length from the current page table context. + + @param[in] PhysicalAddress The physical address that is the start address + of a memory region. + @param[in] Length The length of memory region + @param[in] Flush Flush the caches before applying the + encryption mask + + @retval RETURN_SUCCESS The attributes were cleared for the memory region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Setting the memory encyrption attribute is + not supported +**/ +RETURN_STATUS +EFIAPI +InternalMemEncryptSevSetMemoryEncrypted ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS PhysicalAddress, + IN UINT64 Length, + IN BOOLEAN CacheFlush + ); + +#endif diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c new file mode 100644 index 000000000000..a2ea99019917 --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c @@ -0,0 +1,84 @@ +/** @file + + Secure Encrypted Virtualization (SEV) library helper function + + Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD + License which accompanies this distribution. The full text of the license may + be found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include + +/** + This function clears memory encryption bit for the memory region specified + by BaseAddress and Number of pages from the current page table context. + + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use current CR3) + @param[in] BaseAddress The physical address that is the start address + of a memory region. + @param[in] NumberOfPages The number of pages from start memory region. + @param[in] Flush Flush the caches before clearing the bit + (mostly TRUE except MMIO addresses) + + @retval RETURN_SUCCESS The attributes were cleared for the memory region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Clearing memory encryption attribute is not + supported + **/ +RETURN_STATUS +EFIAPI +MemEncryptSevClearPageEncMask ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumberOfPages, + IN BOOLEAN Flush + ) +{ + // + // Memory encryption bit is not accessible in 32-bit mode + // + return RETURN_UNSUPPORTED; +} + +/** + This function sets memory encryption bit for the memory region specified by + BaseAddress and Number of pages from the current page table context. + + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use current CR3) + @param[in] BaseAddress The physical address that is the start address + of a memory region. + @param[in] NumberOfPages The number of pages from start memory region. + @param[in] Flush Flush the caches before clearing the bit + (mostly TRUE except MMIO addresses) + + @retval RETURN_SUCCESS The attributes were set for the memory region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Clearing memory encryption attribute is not + supported + **/ +RETURN_STATUS +EFIAPI +MemEncryptSevSetPageEncMask ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumberOfPages, + IN BOOLEAN Flush + ) +{ + // + // Memory encryption bit is not accessible in 32-bit mode + // + return RETURN_UNSUPPORTED; +} diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.c new file mode 100644 index 000000000000..002f079c7eb3 --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.c @@ -0,0 +1,90 @@ +/** @file + + Secure Encrypted Virtualization (SEV) library helper function + + Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD + License which accompanies this distribution. The full text of the license may + be found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include + +STATIC BOOLEAN mSevStatus = FALSE; +STATIC BOOLEAN mSevStatusChecked = FALSE; + +/** + + Returns a boolean to indicate whether SEV is enabled + + @retval TRUE SEV is enabled + @retval FALSE SEV is not enabled + **/ +STATIC +BOOLEAN +EFIAPI +InternalMemEncryptSevIsEnabled ( + VOID + ) +{ + UINT32 RegEax; + MSR_SEV_STATUS_REGISTER Msr; + CPUID_MEMORY_ENCRYPTION_INFO_EAX Eax; + + // + // Check if memory encryption leaf exist + // + AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL); + if (RegEax >= CPUID_MEMORY_ENCRYPTION_INFO) { + // + // CPUID Fn8000_001F[EAX] Bit 1 (Sev supported) + // + AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, &Eax.Uint32, NULL, NULL, NULL); + + if (Eax.Bits.SevBit) { + // + // Check MSR_0xC0010131 Bit 0 (Sev Enabled) + // + Msr.Uint32 = AsmReadMsr32 (MSR_SEV_STATUS); + if (Msr.Bits.SevBit) { + return TRUE; + } + } + } + + return FALSE; +} + +/** + + Returns a boolean to indicate whether SEV is enabled + + @retval TRUE SEV is enabled + @retval FALSE SEV is not enabled + **/ +BOOLEAN +EFIAPI +MemEncryptSevIsEnabled ( + VOID + ) +{ + if (mSevStatusChecked) { + return mSevStatus; + } + + mSevStatus = InternalMemEncryptSevIsEnabled(); + mSevStatusChecked = TRUE; + + return mSevStatus; +} diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c new file mode 100644 index 000000000000..9ec76708bd7b --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c @@ -0,0 +1,84 @@ +/** @file + + Secure Encrypted Virtualization (SEV) library helper function + + Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD + License which accompanies this distribution. The full text of the license may + be found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include + +#include "VirtualMemory.h" + +/** + + This function clears memory encryption bit for the memory region specified by + BaseAddress and Number of pages from the current page table context. + + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use current CR3) + @param[in] BaseAddress The physical address that is the start address + of a memory region. + @param[in] NumberOfPages The number of pages from start memory region. + @param[in] Flush Flush the caches before clearing the bit + (mostly TRUE except MMIO addresses) + + @retval RETURN_SUCCESS The attributes were cleared for the memory + region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Clearing the memory encryption attribute is + not supported + **/ +RETURN_STATUS +EFIAPI +MemEncryptSevClearPageEncMask ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumPages, + IN BOOLEAN Flush + ) +{ + return InternalMemEncryptSevSetMemoryDecrypted (Cr3BaseAddress, BaseAddress, EFI_PAGES_TO_SIZE(NumPages), Flush); +} + +/** + + This function clears memory encryption bit for the memory region specified by + BaseAddress and Number of pages from the current page table context. + + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use current CR3) + @param[in] BaseAddress The physical address that is the start address + of a memory region. + @param[in] NumberOfPages The number of pages from start memory region. + @param[in] Flush Flush the caches before clearing the bit + (mostly TRUE except MMIO addresses) + + @retval RETURN_SUCCESS The attributes were cleared for the memory + region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Clearing the memory encryption attribute is + not supported + **/ +RETURN_STATUS +EFIAPI +MemEncryptSevSetPageEncMask ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumPages, + IN BOOLEAN Flush + ) +{ + return InternalMemEncryptSevSetMemoryEncrypted (Cr3BaseAddress, BaseAddress, EFI_PAGES_TO_SIZE(NumPages), Flush); +} diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c new file mode 100644 index 000000000000..7cbbf915f443 --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c @@ -0,0 +1,439 @@ +/** @file + + Virtual Memory Management Services to set or clear the memory encryption bit + +Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Code is derived from MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c + +**/ + +#include +#include +#include + +#include "VirtualMemory.h" + +STATIC BOOLEAN mAddressEncMaskChecked = FALSE; +STATIC UINT64 mAddressEncMask; + +typedef enum { + SetCBit, + ClearCBit +} MAP_RANGE_MODE; + +/** + Get the memory encryption mask + + @param[out] EncryptionMask contains the pte mask. + +**/ +STATIC +UINT64 +GetMemEncryptionAddressMask ( + VOID + ) +{ + UINT64 EncryptionMask; + CPUID_MEMORY_ENCRYPTION_INFO_EBX Ebx; + + if (mAddressEncMaskChecked) { + return mAddressEncMask; + } + + // + // CPUID Fn8000_001F[EBX] Bit 0:5 (memory encryption bit position) + // + AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, NULL, &Ebx.Uint32, NULL, NULL); + EncryptionMask = LShiftU64 (1, Ebx.Bits.PtePosBits); + + mAddressEncMask = EncryptionMask & PAGING_1G_ADDRESS_MASK_64; + mAddressEncMaskChecked = TRUE; + + return mAddressEncMask; +} + +/** + Split 2M page to 4K. + + @param[in] PhysicalAddress Start physical address the 2M page covered. + @param[in, out] PageEntry2M Pointer to 2M page entry. + @param[in] StackBase Stack base address. + @param[in] StackSize Stack size. + +**/ +STATIC +VOID +Split2MPageTo4K ( + IN PHYSICAL_ADDRESS PhysicalAddress, + IN OUT UINT64 *PageEntry2M, + IN PHYSICAL_ADDRESS StackBase, + IN UINTN StackSize + ) +{ + PHYSICAL_ADDRESS PhysicalAddress4K; + UINTN IndexOfPageTableEntries; + PAGE_TABLE_4K_ENTRY *PageTableEntry, *PageTableEntry1; + UINT64 AddressEncMask; + + PageTableEntry = AllocatePages(1); + + PageTableEntry1 = PageTableEntry; + + AddressEncMask = GetMemEncryptionAddressMask (); + + ASSERT (PageTableEntry != NULL); + ASSERT (*PageEntry2M & AddressEncMask); + + PhysicalAddress4K = PhysicalAddress; + for (IndexOfPageTableEntries = 0; IndexOfPageTableEntries < 512; IndexOfPageTableEntries++, PageTableEntry++, PhysicalAddress4K += SIZE_4KB) { + // + // Fill in the Page Table entries + // + PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K | AddressEncMask; + PageTableEntry->Bits.ReadWrite = 1; + PageTableEntry->Bits.Present = 1; + if ((PhysicalAddress4K >= StackBase) && (PhysicalAddress4K < StackBase + StackSize)) { + // + // Set Nx bit for stack. + // + PageTableEntry->Bits.Nx = 1; + } + } + + // + // Fill in 2M page entry. + // + *PageEntry2M = (UINT64) (UINTN) PageTableEntry1 | IA32_PG_P | IA32_PG_RW | AddressEncMask; +} + +/** + Split 1G page to 2M. + + @param[in] PhysicalAddress Start physical address the 1G page covered. + @param[in, out] PageEntry1G Pointer to 1G page entry. + @param[in] StackBase Stack base address. + @param[in] StackSize Stack size. + +**/ +STATIC +VOID +Split1GPageTo2M ( + IN PHYSICAL_ADDRESS PhysicalAddress, + IN OUT UINT64 *PageEntry1G, + IN PHYSICAL_ADDRESS StackBase, + IN UINTN StackSize + ) +{ + PHYSICAL_ADDRESS PhysicalAddress2M; + UINTN IndexOfPageDirectoryEntries; + PAGE_TABLE_ENTRY *PageDirectoryEntry; + UINT64 AddressEncMask; + + PageDirectoryEntry = AllocatePages(1); + + AddressEncMask = GetMemEncryptionAddressMask (); + ASSERT (PageDirectoryEntry != NULL); + ASSERT (*PageEntry1G & GetMemEncryptionAddressMask ()); + // + // Fill in 1G page entry. + // + *PageEntry1G = (UINT64) (UINTN) PageDirectoryEntry | IA32_PG_P | IA32_PG_RW | AddressEncMask; + + PhysicalAddress2M = PhysicalAddress; + for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M += SIZE_2MB) { + if ((PhysicalAddress2M < StackBase + StackSize) && ((PhysicalAddress2M + SIZE_2MB) > StackBase)) { + // + // Need to split this 2M page that covers stack range. + // + Split2MPageTo4K (PhysicalAddress2M, (UINT64 *) PageDirectoryEntry, StackBase, StackSize); + } else { + // + // Fill in the Page Directory entries + // + PageDirectoryEntry->Uint64 = (UINT64) PhysicalAddress2M | AddressEncMask; + PageDirectoryEntry->Bits.ReadWrite = 1; + PageDirectoryEntry->Bits.Present = 1; + PageDirectoryEntry->Bits.MustBe1 = 1; + } + } +} + + +/** + Set or Clear the memory encryption bit + + @param[in] PagetablePoint Page table entry pointer (PTE). + @param[in] Mode Set or Clear encryption bit + +**/ +STATIC VOID +SetOrClearCBit( + IN OUT UINT64* PageTablePointer, + IN MAP_RANGE_MODE Mode + ) +{ + UINT64 AddressEncMask; + + AddressEncMask = GetMemEncryptionAddressMask (); + + if (Mode == SetCBit) { + *PageTablePointer |= AddressEncMask; + } else { + *PageTablePointer &= ~AddressEncMask; + } + +} + +/** + This function either sets or clears memory encryption bit for the memory region + specified by PhysicalAddress and length from the current page table context. + + The function iterates through the physicalAddress one page at a time, and set + or clears the memory encryption mask in the page table. If it encounters + that a given physical address range is part of large page then it attempts to + change the attribute at one go (based on size), otherwise it splits the + large pages into smaller (e.g 2M page into 4K pages) and then try to set or + clear the encryption bit on the smallest page size. + + @param[in] PhysicalAddress The physical address that is the start + address of a memory region. + @param[in] Length The length of memory region + @param[in] Mode Set or Clear mode + @param[in] Flush Flush the caches before applying the + encryption mask + + @retval RETURN_SUCCESS The attributes were cleared for the memory + region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Setting the memory encyrption attribute is + not supported +**/ + +STATIC +RETURN_STATUS +EFIAPI +SetMemoryEncDec ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS PhysicalAddress, + IN UINTN Length, + IN MAP_RANGE_MODE Mode, + IN BOOLEAN CacheFlush + ) +{ + PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry; + PAGE_MAP_AND_DIRECTORY_POINTER *PageUpperDirectoryPointerEntry; + PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry; + PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry; + PAGE_TABLE_ENTRY *PageDirectory2MEntry; + PAGE_TABLE_4K_ENTRY *PageTableEntry; + UINT64 PgTableMask; + UINT64 AddressEncMask; + + // + // Check if we have a valid memory encryption mask + // + AddressEncMask = GetMemEncryptionAddressMask (); + if (!AddressEncMask) { + return RETURN_ACCESS_DENIED; + } + + PgTableMask = AddressEncMask | EFI_PAGE_MASK; + + if (Length == 0) { + return RETURN_INVALID_PARAMETER; + } + + // + // We are going to change the memory encryption attribute from C=0 -> C=1 or + // vice versa Flush the caches to ensure that data is written into memory with + // correct C-bit + // + if (CacheFlush) { + WriteBackInvalidateDataCacheRange((VOID*) (UINTN)PhysicalAddress, Length); + } + + while (Length) + { + // + // If Cr3BaseAddress is not specified then read the current CR3 + // + if (Cr3BaseAddress == 0) { + Cr3BaseAddress = AsmReadCr3(); + } + + PageMapLevel4Entry = (VOID*) (Cr3BaseAddress & ~PgTableMask); + PageMapLevel4Entry += PML4_OFFSET(PhysicalAddress); + if (!PageMapLevel4Entry->Bits.Present) { + DEBUG ((DEBUG_WARN, + "%a:%a ERROR bad PML4 for %lx\n", gEfiCallerBaseName, __FUNCTION__, + PhysicalAddress)); + return RETURN_NO_MAPPING; + } + + PageDirectory1GEntry = (VOID*) ((PageMapLevel4Entry->Bits.PageTableBaseAddress<<12) & ~PgTableMask); + PageDirectory1GEntry += PDP_OFFSET(PhysicalAddress); + if (!PageDirectory1GEntry->Bits.Present) { + DEBUG ((DEBUG_WARN, + "%a:%a ERROR bad PDPE for %lx\n", gEfiCallerBaseName, + __FUNCTION__, PhysicalAddress)); + return RETURN_NO_MAPPING; + } + + // + // If the MustBe1 bit is not 1, it's not actually a 1GB entry + // + if (PageDirectory1GEntry->Bits.MustBe1) { + // + // Valid 1GB page + // If we have at least 1GB to go, we can just update this entry + // + if (!(PhysicalAddress & (BIT30 - 1)) && Length >= BIT30) { + SetOrClearCBit(&PageDirectory1GEntry->Uint64, Mode); + DEBUG ((DEBUG_VERBOSE, + "%a:%a Updated 1GB entry for %lx\n", gEfiCallerBaseName, + __FUNCTION__, PhysicalAddress)); + PhysicalAddress += BIT30; + Length -= BIT30; + } else { + // + // We must split the page + // + DEBUG ((DEBUG_VERBOSE, + "%a:%a Spliting 1GB page\n", gEfiCallerBaseName, __FUNCTION__)); + Split1GPageTo2M(((UINT64)PageDirectory1GEntry->Bits.PageTableBaseAddress)<<30, (UINT64*) PageDirectory1GEntry, 0, 0); + continue; + } + } else { + // + // Actually a PDP + // + PageUpperDirectoryPointerEntry = (PAGE_MAP_AND_DIRECTORY_POINTER*) PageDirectory1GEntry; + PageDirectory2MEntry = (VOID*) ((PageUpperDirectoryPointerEntry->Bits.PageTableBaseAddress<<12) & ~PgTableMask); + PageDirectory2MEntry += PDE_OFFSET(PhysicalAddress); + if (!PageDirectory2MEntry->Bits.Present) { + DEBUG ((DEBUG_WARN, + "%a:%a ERROR bad PDE for %lx\n", gEfiCallerBaseName, __FUNCTION__, + PhysicalAddress)); + return RETURN_NO_MAPPING; + } + // + // If the MustBe1 bit is not a 1, it's not a 2MB entry + // + if (PageDirectory2MEntry->Bits.MustBe1) { + // + // Valid 2MB page + // If we have at least 2MB left to go, we can just update this entry + // + if (!(PhysicalAddress & (BIT21-1)) && Length >= BIT21) { + SetOrClearCBit (&PageDirectory2MEntry->Uint64, Mode); + PhysicalAddress += BIT21; + Length -= BIT21; + } else { + // + // We must split up this page into 4K pages + // + DEBUG ((DEBUG_VERBOSE, + "%a:%a Spliting 2MB page at %lx\n", gEfiCallerBaseName,__FUNCTION__, + PhysicalAddress)); + Split2MPageTo4K (((UINT64)PageDirectory2MEntry->Bits.PageTableBaseAddress) << 21, (UINT64*) PageDirectory2MEntry, 0, 0); + continue; + } + } else { + PageDirectoryPointerEntry = (PAGE_MAP_AND_DIRECTORY_POINTER*) PageDirectory2MEntry; + PageTableEntry = (VOID*) (PageDirectoryPointerEntry->Bits.PageTableBaseAddress<<12 & ~PgTableMask); + PageTableEntry += PTE_OFFSET(PhysicalAddress); + if (!PageTableEntry->Bits.Present) { + DEBUG ((DEBUG_WARN, + "%a:%a ERROR bad PTE for %lx\n", gEfiCallerBaseName, + __FUNCTION__, PhysicalAddress)); + return RETURN_NO_MAPPING; + } + SetOrClearCBit (&PageTableEntry->Uint64, Mode); + PhysicalAddress += EFI_PAGE_SIZE; + Length -= EFI_PAGE_SIZE; + } + } + } + + // + // Flush TLB + // + CpuFlushTlb(); + + return RETURN_SUCCESS; +} + +/** + This function clears memory encryption bit for the memory region specified by + PhysicalAddress and length from the current page table context. + + @param[in] PhysicalAddress The physical address that is the start + address of a memory region. + @param[in] Length The length of memory region + @param[in] Flush Flush the caches before applying the + encryption mask + + @retval RETURN_SUCCESS The attributes were cleared for the memory + region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Setting the memory encyrption attribute is + not supported +**/ +RETURN_STATUS +EFIAPI +InternalMemEncryptSevSetMemoryDecrypted ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS PhysicalAddress, + IN UINTN Length, + IN BOOLEAN Flush + ) +{ + + DEBUG ((DEBUG_VERBOSE, + "%a:%a Clear C-bit Cr3 %Lx Base %Lx Length %Lx flush %d\n", + gEfiCallerBaseName, __FUNCTION__, Cr3BaseAddress, PhysicalAddress, Length, + Flush)); + return SetMemoryEncDec (Cr3BaseAddress, PhysicalAddress, Length, ClearCBit, Flush); +} + +/** + This function sets memory encryption bit for the memory region specified by + PhysicalAddress and length from the current page table context. + + @param[in] PhysicalAddress The physical address that is the start address + of a memory region. + @param[in] Length The length of memory region + @param[in] Flush Flush the caches before applying the + encryption mask + + @retval RETURN_SUCCESS The attributes were cleared for the memory + region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Setting the memory encyrption attribute is + not supported +**/ +RETURN_STATUS +EFIAPI +InternalMemEncryptSevSetMemoryEncrypted ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS PhysicalAddress, + IN UINTN Length, + IN BOOLEAN Flush + ) +{ + DEBUG ((DEBUG_VERBOSE, + "%a:%a Set C-bit Cr3 %Lx Base %Lx Length %Lx flush %d\n", + gEfiCallerBaseName, __FUNCTION__, Cr3BaseAddress, PhysicalAddress, Length, + Flush)); + return SetMemoryEncDec (Cr3BaseAddress, PhysicalAddress, Length, SetCBit, Flush); +} -- 2.7.4