From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from NAM02-SN1-obe.outbound.protection.outlook.com (mail-sn1nam02on0600.outbound.protection.outlook.com [IPv6:2a01:111:f400:fe44::600]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 3466621A16EFF for ; Fri, 26 May 2017 14:06:57 -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=H8owhhV1y+g7HNXkNqxVN6TjQiP3ja0Dar1v3OluBA8=; b=L3DWwQW4cIGvYN3nEudo/V4A9S4uCqj9VuLeb9eGBwZp2pFc6I2XaS8zXYpc4OIQV08ccG5GXtpgnNON7yFiFI5HZPCMBsEdy3PPrnprHcmDNEhijYMqPS608dOWi70+bjUXgumsa7XjzWb4/sbmLM6QUGMbaGoaY04e8phjbnE= Authentication-Results: redhat.com; dkim=none (message not signed) header.d=none;redhat.com; dmarc=none action=none header.from=amd.com; Received: from [10.236.136.62] (165.204.77.1) by SN1PR12MB0159.namprd12.prod.outlook.com (10.162.3.146) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1124.9; Fri, 26 May 2017 21:06:53 +0000 CC: , , , Laszlo Ersek To: Jordan Justen , Jiewen Yao , Jeff Fan , References: <1495809845-32472-1-git-send-email-brijesh.singh@amd.com> <1495809845-32472-5-git-send-email-brijesh.singh@amd.com> <149583207795.25973.8215621482706964409@jljusten-skl> From: Brijesh Singh Message-ID: Date: Fri, 26 May 2017 16:06:47 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.1.1 MIME-Version: 1.0 In-Reply-To: <149583207795.25973.8215621482706964409@jljusten-skl> X-Originating-IP: [165.204.77.1] X-ClientProxiedBy: SN1PR19CA0030.namprd19.prod.outlook.com (10.163.220.40) To SN1PR12MB0159.namprd12.prod.outlook.com (10.162.3.146) X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SN1PR12MB0159: X-MS-Office365-Filtering-Correlation-Id: d7a45067-609e-415a-3332-08d4a47b22c8 X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001)(48565401081)(201703131423075)(201703031133081); SRVR:SN1PR12MB0159; X-Microsoft-Exchange-Diagnostics: 1; SN1PR12MB0159; 3:m2o+86LGYzh5vB6PIKVr8vGAFz/VKfV6mkncbaGp8hwPyd5dzuja8jsrxqUia8pZOz/HE2VLqsw6FvtT4NC+scn7aL57fpTYWt/RnKimNMqhQUbuSkNhQYagiBXtkZBYWH/dTx6wt38M1Pq6En2VU+ooLE1201ckwR7ee1mX6gHvU/FUqJtgFoiqg/FougLbDyqwqQjjEoyBuPzQq17CWpNcwT2Xghq8NXvuH6k7K1Ml+5v8v7r4fEFM7Vk5cABuD1BvkAKeaZG5LHQ1lQOKFkxpmonMRfmaFMcbXS7SjvQo2/tPhrdodMx2ANdHO2Nnukk2FXc4mW0WJjwCoMM16YMZQc5eNazp+VRD8rMzzlU=; 25:6hSrCLSSGOtyKlcp6F3GYPI69S0yq8sZ47lvw1nNZ+RdrcNwibE8eAHbx6QZYkdenjwTWLjdwq0WAjHpvI6qhQSQLlP8NPu1YGjUcPr/y/wddD/ibYdM5QD3bIZ62eaGZWX5gtYZSoZXQyLKHlqsG11IWLy08v86VDfzsMFjQRzVMqTs0uUzy4LJ2eE6XhCdVgBijCQcM3fzZuaVW/G4O1NgcjaASOWuYEIhZe3WWRM/rKW1e0BDCZ/38FPEIHH8tQ6ZSAhv3CDzKa3kWNhnOFXc5U33MV/Z28C71lMYWTTnc3NVB2liU9vfPQ4MPh5EefWGjETpuLpMZKJHWKHO+Pw5Liw14udFVsGmnb6GO2PWy59ziLfOAx92v0MyJ0S4RWI5yzZr9oAheBShas8giOTnrv6Xlk0Z/ZS+nT5hN2jGySPx3Vf0FVsf/GnZ6uQZZtu9ITv4Qk4GkgxD9mt6S3GQPY9S5QAUzM27dTq+Wec= X-Microsoft-Exchange-Diagnostics: 1; SN1PR12MB0159; 31:aWY+3eREL054AVA5sPrNska9tQsH0RXwVdEF6tRM4ze064KUoUmXY4eTSVXN/03kS22OlTCECNhH1Pl/jsgg1nQ9qOzEzUWvLJsNb40WEaBbt+AOTSL003XUAV6Xij5OqIf3LxLtINqlO3p2R4eCwVWSiJmtbWixmwZ2ldjf1krtsUWsJLm73Ktsp/r9IZim+L5zr8zhMYYTNcCgsmvcUn/zUgUzy9ltjCjgAHUm0Zw=; 20:fAN0U9txHD7fWx0+udDEpMNKN96UqOYqZfQAi6bBr2hWaBSA8S5GU/c+d0fbj6Z1ctjcVBYWk7h7O+/EtpWEQkULpuRCMiCw1wWtoqOVNfnHEH6r5cdcqql7gAbLyiblSx6WneVmvQOhefaOJWas3fOyIaGTtz708/meCIxLo9dkpTmhNdtOG7KmWHfSdIAOjJox6OH32kB17OG7YTwl6M0L4En6nzQ3POss4Yy/ZkaeBLI4F4kBOfjOmGKYhGkoGllMpZhKQCy0+tpoiYmlNZC1J5MShz7mcNpR4mKYSUlRCe/d4Sff6/7cBNL559jF1cqm5RmZKEmz7r7A2lxgFKaL/zZ97JvPJwBnHRStwCa7hMbxGc4XpP661bhJyPuvICNkROuVHjSi3vLRvUrkZvrt62GAqMHcTcYuRy2S56IfJzprCmwPsFRvyfr/qOggV1KQNdSXYFf6TW2utBa0BJLZipwyo1Q/eXWTjkc1eXtVRLuyRZdZRuEmvSjP+GCK X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(767451399110)(228905959029699); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040450)(601004)(2401047)(8121501046)(5005006)(10201501046)(3002001)(93006095)(93001095)(6055026)(6041248)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123558100)(20161123555025)(20161123564025)(20161123562025)(20161123560025)(6072148); SRVR:SN1PR12MB0159; BCL:0; PCL:0; RULEID:; SRVR:SN1PR12MB0159; X-Microsoft-Exchange-Diagnostics: 1; SN1PR12MB0159; 4:+hcZNXv/M0Sku771VG9CwPeIJmhDaFKggPbXSd8hMOUXijL6FBTnFiHrUlf3nmBvKdDbG+7eoQDGCy3xZ0xaHrg/NT5zkSzbCY521hvJg7Wap5rv+b5nKhcr6oug5A8z+urbpaKCbJfEwA+dVlHff/XZBdpbafnLf4PJPM2pxjZuiKz917dFcGRoKKjcsAsK4x/HOvC9baKou6fbtiZD7+Rwvdo8lfRMgnyxCEZ6tO8Pztl9ZEJpG6iVNevweWJkV8bLc8irv2Ldw3Jk7twSiaU2eDZwKjotXnrP8oirfyIuGdp5zPGGOFUmATGY2YG1+wa09A6NNIpwT023IDOy01y41k4x+6u5ePgyHCB3BE/+ht6VYga6q6OsLjsclekIZW6MoQRjAPEIbtiz5R7zpgJl9PhDZqbkDD81OQks0IPsTfxT8ZdlF8hZF6I7cASnp5iQJGwVR0p3A0u8ZpSoY3zRcH4KwerOjz4NIQFVIfvOt1uS0OgXiiRw4GGNFJNLzLubl7dSTLDI2eZeO8WdsB97W7G9hoVlX6e9/smoMbaq+qTppi283Mxj2GbROUKKOgY+1tv6e+98CLplSj6Zkh+ZrWpuArWIs0cVK7/FrW0G2lOgeYPe5D5bFfAyEH00414hpUM/u6ZbvCZio83R2lO57+a4oOELN6iFzpf5GF6Hiq7oi+lJWvoZoGJ7tRm31qTPf6eRaVA8sFq+GPHZEYY1GROpPKJITnGyc7hGroEXtJj7Ou0Io7ZjaHkS3TXaiBWexXbiNRAUaBls71ApKaaAnOLRewpDHPYOQohaSCWSxI9HqNRTlYo1Xqojhh0ByjxMULOQ2QOYASs9xeGGasdzn0gPhvKM4WlmkJBbaYxLovi5HsasPKg5odTfKdya X-Forefront-PRVS: 031996B7EF X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(4630300001)(6009001)(6049001)(39450400003)(39860400002)(39840400002)(39850400002)(39400400002)(39410400002)(377454003)(24454002)(377424004)(50986999)(50466002)(8676002)(305945005)(54356999)(7736002)(54906002)(66066001)(31686004)(15188155005)(81166006)(6306002)(42186005)(6486002)(2950100002)(90366009)(36756003)(5660300001)(77096006)(53946003)(230700001)(189998001)(6666003)(229853002)(575784001)(4326008)(76176999)(83506001)(47776003)(65826007)(966005)(33646002)(23676002)(478600001)(2906002)(53546009)(25786009)(4001350100001)(16799955002)(38730400002)(86362001)(3846002)(6116002)(53376002)(6246003)(53936002)(579004)(19627235001); DIR:OUT; SFP:1101; SCL:1; SRVR:SN1PR12MB0159; H:[10.236.136.62]; FPR:; SPF:None; MLV:sfv; LANG:en; X-Microsoft-Exchange-Diagnostics: =?utf-8?B?MTtTTjFQUjEyTUIwMTU5OzIzOlM4aUtoSjBlR0Y1SjZFcWtuWk5FSlNVN1h4?= =?utf-8?B?SE5LcC8wSkM3eGF4ZnVLNlNublc5TDdHaEVQZm0rbzNxb2NqV2VWUm5HazJY?= =?utf-8?B?WmFrNEVnQ1VEQlZibDVmc2t5aFMzNmpiM2FPYm9VVFZZWWFadSszNHoxUmhJ?= =?utf-8?B?cEZuQUJVcTlNaWdMRHZSREFDakE3QUgxV01QVHBUWm9FRE1oRmcyM28wdEZM?= =?utf-8?B?N3N0RktPR2JQaFhlQVVwMWZNSzBXUElaMW5pMy9PeHc4ZlBJaEk4aTM5eHI2?= =?utf-8?B?cnZpWi9VOGFyckZqSXJkL1NsK0JlZExTYUNIMDVKVTFKQkFrWW12UVUzTm5t?= =?utf-8?B?SWF4VkxhSDNTQXBwNmgybmEwNldJN2tNeHFKNmliNGpNM1pLR2VGa3VOR1Iy?= =?utf-8?B?U3l4UGw2V0VvZUJlT01xaDVRdjRnY21Wdy9yNU1LUUt6WU9IV281SFpnWnBV?= =?utf-8?B?N0ozRUx6VklXY1lIVVVjNW4yMzBCTjRqMy9HaFhmWXlrRmtzbWdvdnFyTFVV?= =?utf-8?B?Wkk1bEhvS0hFVWZtc0NYV2VXL0dod0RiWU4xeFkzVjQwRkZMTzhHK0ZkWkdJ?= =?utf-8?B?Znp4L01uYWxDSzZodDA2czlOTXhxQ0NETTlsNEp0OGhRMjMwYUdRa0pSdXho?= =?utf-8?B?UkNTc1BUaWRTbkdLYng2L1pIV3hRS2pvVVNLWklQZFFGUG4rNjVKU1d0WW1R?= =?utf-8?B?bCtsaVlxOU85czh0dmF6WlpXRC83L3prUTIwbC9GS0FXNEZEbGgzRnN4Zmt0?= =?utf-8?B?N2NuRUJROG1zV0VqVTlVRVZmNmRsN0dVazNWcnA0SW9LdVk0cWNRTmZha1h5?= =?utf-8?B?dWZKUW9nd1I5WEZ0YmNvZU9IaGNVTFAvbEhOVVA2RWNJdy90eWdPYUZuMCsx?= =?utf-8?B?OVdVVDRORUFleGVrc2ZuZ243em1nNHQvc3d5eEQ0SmNpNEh1UGhnaDBHS2Jm?= =?utf-8?B?ZGZhUFJZc1docDZxYmppVDN4Q2wzcTF1eXlxSFR5RjFqcG5PalhPRmMrcTBK?= =?utf-8?B?Rlo5VTFYZExYeS9hRW1SRTZZS0d5M2NqK29xVnlvL0dqRDR0V1Rwc042VFlq?= =?utf-8?B?bmFUKytRZWRCTjhaQkxsbjVOeG00MDFmZkF1elBIRitiTEd1V2VpNGdUT1ps?= =?utf-8?B?MUFIY3Bla1FOQk9GMjZGd1p1QklBNlQ5dDBxNDJJd2I0N2xwZlVqMWxYQVRN?= =?utf-8?B?VmIzdm1ualByQ0VoZE5MbnY3RG9sYXh5aEo4eS9WZFFuYjNhREIvbXIwbG5Q?= =?utf-8?B?bm8rRXhuZjR0Z2R5Y2F6cENHbVhUcWtIMGh0SW1lMzQzK1AycTNiWkNNN0RX?= =?utf-8?B?MjFRK1QxN2dUS3lCUDloeUV4T1FqQld6THZpUEI1UHFQWjQ2Q3pWdUxoSUtD?= =?utf-8?B?Sld5UkFHVTNKaVptQTg4Mzl4YXJvMUE4c1hQMkVwZklXYjBuQTVVam44dFJk?= =?utf-8?B?NUF5WStnOFZheHN2bTUvU2dJRGNQUlRUYWwrYTBTSmgxYlBya0VBdE84TVlT?= =?utf-8?B?azdJMW5rdUhaSEkrbnVXdSt3M3dSNkNTYlh0WTJWdzVSNmFjbFpwTE5hM2sw?= =?utf-8?B?c2N4MHY4ejlaYkhCcTlmZnFwOHJuUHV5azczSzJNd3NmYmZDS291alE1Qmxq?= =?utf-8?B?VVdEWlQrK2pxTHpOQ1ZyZU4vRUhjSG0ydEttT3pLN0FobEJIcFhoNFhMbFow?= =?utf-8?B?bmtCUVBrOVdLOStwQkx3S0NvQWdJWEtqVzZpK2E4aU9UbHRjcXZZV3JIRkRS?= =?utf-8?B?SU9nRUFmanZxR1habzYrZzVDSTNMTVlndmdzMjN5bGlrMGhLK1grVVlnQ0kv?= =?utf-8?B?dUxndmNpVG1ZOXpnSElGbFFvYjJoRUJ6R1Z5UFNqRXpsMHB2QjJyOENrUXVD?= =?utf-8?B?bXZHTm1BZ2QzaUZYOU12TXZVVmdiajdqRmpRU0Jwa0lFN1Y5RzFQZy9DNklL?= =?utf-8?B?azFXd2k5SFB3L0xhSDBlZ2pSUkRnaElnN2xMZmoxb2E4UGxPTzJ3bXV1VEN5?= =?utf-8?B?WTlFSEZnY1AwcmgvQTBGaUk2ZURHeCtLQ1MwUT09?= X-Microsoft-Exchange-Diagnostics: 1; SN1PR12MB0159; 6:nwddfIeIrcXI8X64bac7/tToyvzH92NDO/7T6lQE5hQSSN/kQkUXlSrl7ldxnmuGjV8K2O+pJn88Vq+sa4DgYxL+F63ikcL8CnyQ3kcjpgFO01q9+wawJ9Y+wPCEkPysVFtRygqI5ajdbep1C5mN9C7TbOxz54a1w52of2ZxnETwxr+6/Bh1+gLshVzVKPF5PhRnoJI+zaI5M0q9OES4GnjLiGOFhpHc3V+mgF3U7hcwKXaCasCBpE4l6K8Al9yX9IivsVHrdCkaI2aJ7UYWWwmfxGT9gfzOPCfji5LToazqh7zUYble73iLeRH1YUVPhcqf3f2FzWXehNh0Qv0Nv41GnSGc7EHZclFGXR0q5kCjQfOKOdwTwA05THUA8seycStEFCySyx2l+8x7JClHUgAX7ueH7AL9o4bbVgrJBdJ5XT3dj727heDSKjmaLljO2HP1t9ftc+Z6eI6jf5c6SPJYb0ozZ99te2OsuGql6JAP0bDzwpf5H18KDvNVF6ROmgGUPpUYTO+ndor+5sGwh7mxLTVAujsPbswL9k1JaGI=; 5:8FuSM0dsAukKQ5FBVsW7v/mbt6DxPCo04B77KJhU1gPVzMczsirZ+3/zJSdhRrApPn9HY/lKkTT7nIXT0gDmsZzC1cVSojHMEW9cPbu3hXRHnQPS4hfV8ttm6a722OpEiYpYHMFhafaWkAMwFt4rMA==; 24:EUpT/DsxtuPELhVQ5z1ZYh1v3bd9KtA7A9gg9Uf3wi0UNxpPbn307oLmsHZnZEVr+EjMXw0BZTdTuA9lsSx+eOdWWFfPwXo30EU5Abvoj6w= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; SN1PR12MB0159; 7:e4pBerRhipFHxRYsABUgy/kUBv/ZvYRrZBK35iIHsWDcP/4jBE0imEChITHn6tX5X5ThkcF27zro8lGE041HFfPU46EhMYvVovICAwsFJlYc8WjETUbpFvsBcJhHk/cphXbYz5oqcyqOlxOJln5AcCA1yJLC5VLPlUMj2zFsKuZKzLmrxnPoPIKrzR1J15E4wS+aMZ2HxsBAdG3cM2Ug/3U45s0l4XCVN6mXNUnafcNpfeZyOCZQpyXp6kFK75JlZV/4jGg5ynsZ5np/KRK24ggfVQA7aCk/kaFmSm2AVMcVa6nT8b+FwHPVFloUfHTy+f1tsZxzEnbFYRqy2G8HcA==; 20:3BdRmjZJUk+mJ9lsuRzIWKmpkwTGtsn5nfv19iabZAzFazcmWyjvJ1auykXsnuBpKBRFLTRp6esCc/YsHy5HZX2tw5YV4+p2sIemHbYb2wNZvSpBaUZwU7Madxq5/qpk+Xaofx45kGwCVK8L3OIAE2wqrSCZ/+iqOF3UJj6lbv9eRKnuWR6GcCAYluOMpAU4UpJkOaHMuj24BApDetbtLKW+ErVukSVD9yzHK2zWLa3H+sapMkpN/7tLDAtUrQYM X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 May 2017 21:06:53.5060 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN1PR12MB0159 Subject: Re: [PATCH v6 04/17] 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: Fri, 26 May 2017 21:06:57 -0000 Content-Type: text/plain; charset="utf-8"; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit Hi Jordan, I don't have any strong feeling on where this lib should go, but since SEV (Secure Encrypted Virtualization) feature is applicable only when are building/booting the OVMF platform hence I thought OVMF is the right place for it. Thanks Brijesh On 05/26/2017 03:54 PM, Jordan Justen wrote: > Jiewen, Jeff, Brijesh, > > Is there a reason this shouldn't go under UefiCpuPkg rather than > OvmfPkg? > > -Jordan > > On 2017-05-26 07:43:52, Brijesh Singh wrote: >> 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 b5c874b65afc..98691c0a6d99 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 1d071cac2bef..3b51513a4d95 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 2bea75437788..ebf07cd585dd 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 >>