From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by mx.groups.io with SMTP id smtpd.web12.3913.1617259082554286005 for ; Wed, 31 Mar 2021 23:38:02 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@intel.onmicrosoft.com header.s=selector2-intel-onmicrosoft-com header.b=AhSP4ol9; spf=pass (domain: intel.com, ip: 134.134.136.126, mailfrom: jiewen.yao@intel.com) IronPort-SDR: nEmciGrmTpm6KYNvKHvas15MrAJDIzC+moTReCOioBlGxYCuy3EmEOyonaYEoprINXKU6lu3Ud FjvdV+F5GlNQ== X-IronPort-AV: E=McAfee;i="6000,8403,9940"; a="179697087" X-IronPort-AV: E=Sophos;i="5.81,296,1610438400"; d="scan'208";a="179697087" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Mar 2021 23:37:57 -0700 IronPort-SDR: X7YrUFIfq1BmMfhQ+rUKH+EmdwbgIlagEAtBi1Za2Mr+alLc65XMEyZoGPWJsPyhAUhdoHzdN5 cOLKkC9E6rag== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,296,1610438400"; d="scan'208";a="446095404" Received: from orsmsx606.amr.corp.intel.com ([10.22.229.19]) by fmsmga002.fm.intel.com with ESMTP; 31 Mar 2021 23:37:56 -0700 Received: from orsmsx611.amr.corp.intel.com (10.22.229.24) by ORSMSX606.amr.corp.intel.com (10.22.229.19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2106.2; Wed, 31 Mar 2021 23:37:56 -0700 Received: from orsmsx605.amr.corp.intel.com (10.22.229.18) by ORSMSX611.amr.corp.intel.com (10.22.229.24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2106.2; Wed, 31 Mar 2021 23:37:55 -0700 Received: from orsedg603.ED.cps.intel.com (10.7.248.4) by orsmsx605.amr.corp.intel.com (10.22.229.18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2106.2 via Frontend Transport; Wed, 31 Mar 2021 23:37:55 -0700 Received: from NAM12-BN8-obe.outbound.protection.outlook.com (104.47.55.174) by edgegateway.intel.com (134.134.137.100) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2106.2; Wed, 31 Mar 2021 23:37:55 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=N8R7WXw5RWLbBxFbe69igzjbM0RyNbRCKDUBFHkvIzcuZNhKExz4B9D5iDSqMuAfu7zdgmo50TId8tjrvvYuOiMgWPt6NTuNJ+2yM7dPsc/x+drDhsOG+oyJ7DGS1C/gNEPzy3ec5AR/dLht1L7lTmhJYLngey9Bhfd9lo9+MERgQXKw9CMZTMiH5gYk1B8tQyeccZl7ez9okepNxlixoQb9r+Yfj3fjq764ozPPBuO/234sbLrvn26uVlRj3yklZwR1cV58PV7mj7ObLsZaEZJULbIttYNryxJhFMREP0b46tqQFokAzvPl5vaP9kT3/Uhj4EJoCji8EeU9g1kKBQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=S4g225W0JCElI70w0x/LVXPiKGjk5h8Fr858/JkpB5s=; b=nkRuGTf2dI9RpD2rkPEggjTDxegM6bQGk5nCOVFouVdSUMvcCDavKP9GoJq0/s25T/KJt8C0V++XAY3TMJ2vwNSNF3ASq05PdJixwXPnC2xeEGuTKrM95blyYXscJtPWPsLgokqCvTju/eF6CnKg5bridd9a4/lYI/lW62gZuoik3/MWcxi7iRIuVFePYGHIh5lYkPoXr91+sXj9e2IgMZAu6CSVz5uAb7txIDXGpIeh/YLwsQyG23lbQyPLFUtii/ZSYNP2el/ICk7MfZFzR2iwlA7ZyEvW8EuhMEJ1xpkBKq21SRz2k+bjTKxKs9jyX4B/JjtaH5ZkKuJN+P21mg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=intel.com; dmarc=pass action=none header.from=intel.com; dkim=pass header.d=intel.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=intel.onmicrosoft.com; s=selector2-intel-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=S4g225W0JCElI70w0x/LVXPiKGjk5h8Fr858/JkpB5s=; b=AhSP4ol9ZJFzOpqHoropN58dWbYExtn8IuuYtk6X+UM8sPesPLMo4kXWdN2wfH8xEV+Ch7djqZn2x4LEAYEW71HLSh7Hbk4Cd7nqB4D1nbhPvujIBgg/b0bliatUBHlmHDhS8TlBLBJSoEtQ2am54nKI/MB16wOXk4l+lNhxJlM= Received: from BY5PR11MB4166.namprd11.prod.outlook.com (2603:10b6:a03:191::25) by BY5PR11MB3992.namprd11.prod.outlook.com (2603:10b6:a03:188::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3999.28; Thu, 1 Apr 2021 06:37:51 +0000 Received: from BY5PR11MB4166.namprd11.prod.outlook.com ([fe80::5983:f233:56d6:8132]) by BY5PR11MB4166.namprd11.prod.outlook.com ([fe80::5983:f233:56d6:8132%4]) with mapi id 15.20.3977.033; Thu, 1 Apr 2021 06:37:51 +0000 From: "Yao, Jiewen" To: Brijesh Singh , "devel@edk2.groups.io" CC: James Bottomley , "Xu, Min M" , Tom Lendacky , "Justen, Jordan L" , Ard Biesheuvel , Laszlo Ersek Subject: Re: [RFC PATCH 12/19] OvmfPkg/MemEncryptSevLib: Add support to validate system RAM Thread-Topic: [RFC PATCH 12/19] OvmfPkg/MemEncryptSevLib: Add support to validate system RAM Thread-Index: AQHXIML0bBcNg6DJn0+aqJf8+DupSKqfQPXQ Date: Thu, 1 Apr 2021 06:37:50 +0000 Message-ID: References: <20210324153215.17971-1-brijesh.singh@amd.com> <20210324153215.17971-13-brijesh.singh@amd.com> In-Reply-To: <20210324153215.17971-13-brijesh.singh@amd.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-version: 11.5.1.3 dlp-product: dlpe-windows dlp-reaction: no-action authentication-results: amd.com; dkim=none (message not signed) header.d=none;amd.com; dmarc=none action=none header.from=intel.com; x-originating-ip: [101.87.139.49] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 30cda595-0446-49e4-60fe-08d8f4d8ac1e x-ms-traffictypediagnostic: BY5PR11MB3992: x-ld-processed: 46c98d88-e344-4ed4-8496-4ed7712e255d,ExtAddr x-ms-exchange-transport-forked: True x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:10000; x-ms-exchange-senderadcheck: 1 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: o8dGFlANUUJKLrisN65sVwr7VrHlEJn3QitMV9fM4Tpl74moQnkaWlqdtJnXIq6Gojp9jHdrmC7VhCT77W8ef/hOSgoOUkee0qvJakDyYVEWD6kfhqCQuijqsNhY9mrqNDlFDMye0Vg8N88xVFSv9aavhnC+//5FE/KCXXd4vysTV9u3xqyiaLeVeupfi425hbt3gNkiAAns0eNpiexoy9beetamoHmTj9FaqHeYC3ESnNlB3GmpEuQUxkAo4mapC2sfNSiPsL4LEjPoZl8dpusCXcjHAleIT/jYS2dwf9UlRTgnhFWASUK8THDPOSP8I0PDVyHo2GNeozTR3Q/CpYxvAcoend96cn/fhwOOJU9qi7yUyJpwv02UosEQJMKHXbcGf+AYKtsegPnMk6BTT6pc9ycWKLdVi3rbYRtvHf8CmzqudnIoKjmBEZ2IpzQX84AnpAMHxw+ftoA/FWwpa6LxFqpd2cFvdk81ldJkSEBZ1X6cfXbDLM01z9T1sVpR7Khx0DSFvuShTgNcC5KJJSDv2ZEbaMy6rLZ5OkKSEHrx/0nQMVh4J7zcEQoZTKTwQW+Yc4S+HR6adqqmmOOpcOPcHBGEP6fOUW2CqjnV1ziLqdJDy+o/QTpv9wXeve0q4qAny4s5r4WaBXIOyPyqq71yF2CXFGhTe9rfQDIPzMsPBjdFQ5pLef/7wlLvCkysUiXEWCMJPUaG+O2xfovbyHBDoAPV0l2ubLw23uEETczbBpxz3iJ6P2BFoczcV5M0 x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:BY5PR11MB4166.namprd11.prod.outlook.com;PTR:;CAT:NONE;SFS:(346002)(376002)(39860400002)(366004)(136003)(396003)(6506007)(9686003)(8936002)(53546011)(86362001)(55016002)(66946007)(45954011)(2906002)(38100700001)(8676002)(7696005)(83380400001)(110136005)(33656002)(478600001)(64756008)(66556008)(66446008)(26005)(316002)(66476007)(4326008)(52536014)(186003)(71200400001)(966005)(19627235002)(15650500001)(76116006)(30864003)(5660300002)(54906003);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata: =?us-ascii?Q?1750x+aH4ibtxBHRCDrRDE2pmOC4xNIbB62nCeqfG3kXSY5OvJiLH92us20T?= =?us-ascii?Q?b0i0yOjTscbX39tQN7NWbmj94Nk9zFuvfI3xvGXQX63iZwfaPOnuklmTCBmk?= =?us-ascii?Q?OQJBsabt8MSLux2n7E8dc2JPtsVFwZt48nP46YOFJpn4L2uKzVbfAE3mcxTE?= =?us-ascii?Q?45Q6SWple08PTf3QrijAp/PIT/JnWqH8OWcmHGBvQw6vJ9sXfwutfCDivgT9?= =?us-ascii?Q?sNsxGG/nQuMZ4/2m5O1o5TbbfuHFZeACyug39vn3d5oot6s9m77pIikmA6nC?= =?us-ascii?Q?30eIu/oTp+dYkDsu+/yBIdiDv4JhfjSGJXR3MxDZo/zWQrzNV5YMTZyzeOv4?= =?us-ascii?Q?qZwvF1yBFZksB4UL8e62yNP8eQ1TMnUwObDYzTFKHRssfaPRu/WNuEX2/pVf?= =?us-ascii?Q?poO5opsC8vT02uXddM7XEJNHlCTiOGpd6yqNBMFlTexJgZiAol6N3sc/QNqM?= =?us-ascii?Q?jEUH+txaGRNiWRCC0D11tWU8yj0uDimVflyvQABRW+n2DvqlC7p2Hl/QY6WL?= =?us-ascii?Q?T6EWDDv7M2xkl4H0xUSIhsGJGe0ZJB5IJxCt7SSBI+Pf773JnRkZjGpZxxxQ?= =?us-ascii?Q?SXArJuGFDoizyZk352A64u+CTsKILecX/otZ1Y5zSOhbU7cOwy5UmFBJ72qI?= =?us-ascii?Q?1f7qC3UR/J7mcXZR8Tv65tDOD+JRecTQgzyuQg+nVAvNdvF4V35Z74Crs/Q6?= =?us-ascii?Q?L9nx3olAoB2Fm/mB4JXs2aKzIiKdOZsmUXvcrnZUPTa+zySRXyGKf0UjQFU/?= =?us-ascii?Q?DGJvCIsg5bIV1bug48V0757bzxHTMJdiRXdXmPuf7H2JMdL45HQe5I9woKCH?= =?us-ascii?Q?3l1bLP68YuA3s5/tHrv7DW8TYTOWu+ZIhu5e4SaUZs7ZNKkQ4KtdwwlS9ClH?= =?us-ascii?Q?QP2N3IQvnWGTphq2WFbSZ2YRza17ECihiOtdAlDNtwe1fOa1jjp9GVSQQntU?= =?us-ascii?Q?QyV+Vd+ANOflr+Usu1e1oYH2D/HfVqZ1OdvsY6/VSUyXUL1VXgQpGcUd4oTC?= =?us-ascii?Q?7kEmXsJs9REhm8NVa4wGQ3byskFz6f49oAYrYT7rkQQniyFXLiUB8dCEIKd8?= =?us-ascii?Q?RP4uMcU3/z34VZtix7Aa1cYwAIIgxM4z+Mu52qqpNn52EF2NqHKp85U/t+ZD?= =?us-ascii?Q?HbYCwLTPvjp/phJrIC2WaMO668loAVM8AbFv8D0QtNHNj4JzloyzGvMNFnCB?= =?us-ascii?Q?QW3BW2NwoMsiR0OA215gtgH+n77BxlCbIDXMW7dHz9JJ6v5otVpFBX0QU8Ni?= =?us-ascii?Q?W1SGu+v8rFXNAgtEn00+AMOEZJIyMVu9xvNrcfDk/F4i5GR8OJTjnIPtTIiO?= =?us-ascii?Q?CzzEI92KWvJafOp9ROzL1heq?= MIME-Version: 1.0 X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: BY5PR11MB4166.namprd11.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 30cda595-0446-49e4-60fe-08d8f4d8ac1e X-MS-Exchange-CrossTenant-originalarrivaltime: 01 Apr 2021 06:37:50.9511 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 46c98d88-e344-4ed4-8496-4ed7712e255d X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: 6rU2oOLh+SKCux1YPdjHvXt5Ls633K18p4+jqYo5ogGRFPxOfsAB8yPjuU1E8VgvusMPOP9sg43tOFlLi3REVg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY5PR11MB3992 Return-Path: jiewen.yao@intel.com X-OriginatorOrg: intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Hi Would you please clarify why the IA32 version implementation is empty? Does it mean IA32 does not need validate? Or IA32 should never call this function? Anyway, I recommend to add some comment to describe it clearly. If it should never be called, I recommend to add ASSERT(FALSE). +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/SnpPageStateChange.c @@ -0,0 +1,17 @@ +#include + +#include "../SnpPageStateChange.h" + +/** + The function is used to set the page state when SEV-SNP is active. The pa= ge state + transition consist of changing the page ownership in the RMP table, and u= sing the + PVALIDATE instruction to update the Validated bit in RMP table. + + */ +VOID +SevSnpValidateSystemRamInternal ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumPages + ) +{ +} > -----Original Message----- > From: Brijesh Singh > Sent: Wednesday, March 24, 2021 11:32 PM > To: devel@edk2.groups.io > Cc: Brijesh Singh ; James Bottomley > ; Xu, Min M ; Yao, Jiewen > ; Tom Lendacky ; Justen, > Jordan L ; Ard Biesheuvel > ; Laszlo Ersek > Subject: [RFC PATCH 12/19] OvmfPkg/MemEncryptSevLib: Add support to > validate system RAM >=20 > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3275 >=20 > Many of the integrity guarantees of SEV-SNP are enforced through the > Reverse Map Table (RMP). Each RMP entry contains the GPA at which a > particular page of DRAM should be mapped. The guest can request the > hypervisor to add pages in the RMP table via the Page State Change VMGEXI= T > defined in the GHCB specification section 2.5.1 and 4.1.6. Inside each RM= P > entry is a Validated flag; this flag is automatically cleared to 0 by the > CPU hardware when a new RMP entry is created for a guest. Each VM page > can be either validated or invalidated, as indicated by the Validated > flag in the RMP entry. Memory access to a private page that is not > validated generates a #VC. A VM can use the PVALIDATE instruction to > validate the private page before using it. >=20 > During the guest creation, the boot ROM memory is pre-validated by the > AMD-SEV firmware. The MemEncryptSevSnpValidateSystemRam() can be called > during the SEC and PEI phase to validate the detected system RAM. >=20 > One of the fields in the Page State Change NAE is the RMP page size. The > page size input parameter indicates that either a 4KB or 2MB page should > be used while adding the RMP entry. During the validation, when possible, > the MemEncryptSevSnpValidateSystemRam() will use the 2MB entry. A > hypervisor backing the memory may choose to use the different page size > in the RMP entry. In those cases, the PVALIDATE instruction should return > SIZEMISMATCH. If a SIZEMISMATCH is detected, then validate all 512-pages > constituting a 2MB region. >=20 > Upon completion, the PVALIDATE instruction sets the rFLAGS.CF to 0 if > instruction changed the RMP entry and to 1 if the instruction did not > change the RMP entry. The rFlags.CF will be 1 only when a memory region > is already validated. We should not double validate a memory > as it could lead to a security compromise. If double validation is > detected, terminate the boot. >=20 > Cc: James Bottomley > Cc: Min Xu > Cc: Jiewen Yao > Cc: Tom Lendacky > Cc: Jordan Justen > Cc: Ard Biesheuvel > Cc: Laszlo Ersek > Signed-off-by: Brijesh Singh > --- > OvmfPkg/Include/Library/MemEncryptSevLib.h | = 15 ++ > OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/SnpPageStateChange.c | = 17 > ++ > OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf | = 4 + > OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c | > 20 ++ > OvmfPkg/Library/BaseMemEncryptSevLib/SnpPageStateChange.h | = 37 > +++ > OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecSnpSystemRamValidate.c | > 23 ++ > OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c | > 254 ++++++++++++++++++++ > 7 files changed, 370 insertions(+) >=20 > diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h > b/OvmfPkg/Include/Library/MemEncryptSevLib.h > index 03d9eda392..47d6802b61 100644 > --- a/OvmfPkg/Include/Library/MemEncryptSevLib.h > +++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h > @@ -215,4 +215,19 @@ MemEncryptSevGetAddressRangeState ( > IN UINTN Length > ); >=20 > +/** > + If SEV-SNP is active then set the page state of the specified virtual > + address range. This should be called in SEC and PEI phases only. > + > + @param[in] BaseAddress Base address > + @param[in] NumPages Number of pages starting from the = base > address > + > +**/ > +VOID > +EFIAPI > +MemEncryptSevSnpValidateSystemRam ( > + IN PHYSICAL_ADDRESS BaseAddress, > + IN UINTN NumPages > + ); > + > #endif // _MEM_ENCRYPT_SEV_LIB_H_ > diff --git > a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/SnpPageStateChange.c > b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/SnpPageStateChange.c > new file mode 100644 > index 0000000000..dace5c0bcf > --- /dev/null > +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/SnpPageStateChange.c > @@ -0,0 +1,17 @@ > +#include > + > +#include "../SnpPageStateChange.h" > + > +/** > + The function is used to set the page state when SEV-SNP is active. The = page > state > + transition consist of changing the page ownership in the RMP table, and= using > the > + PVALIDATE instruction to update the Validated bit in RMP table. > + > + */ > +VOID > +SevSnpValidateSystemRamInternal ( > + IN EFI_PHYSICAL_ADDRESS BaseAddress, > + IN UINTN NumPages > + ) > +{ > +} > diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf > b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf > index 279c38bfbc..8595e244c2 100644 > --- a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf > +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf > @@ -31,15 +31,19 @@ >=20 > [Sources] > SecMemEncryptSevLibInternal.c > + SnpPageStateChange.h >=20 > [Sources.X64] > X64/MemEncryptSevLib.c > X64/SecVirtualMemory.c > + X64/SecSnpSystemRamValidate.c > + X64/SnpPageStateChangeInternal.c > X64/VirtualMemory.c > X64/VirtualMemory.h >=20 > [Sources.IA32] > Ia32/MemEncryptSevLib.c > + Ia32/SnpPageStateChange.c >=20 > [LibraryClasses] > BaseLib > diff --git > a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c > b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c > index 69852779e2..35a222e75e 100644 > --- a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c > +++ > b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c > @@ -17,6 +17,8 @@ > #include > #include >=20 > +#include "SnpPageStateChange.h" > + > /** > Reads and sets the status of SEV features. >=20 > @@ -172,3 +174,21 @@ > MemEncryptSevLocateInitialSmramSaveStateMapPages ( > { > return RETURN_UNSUPPORTED; > } > + > +/** > + If SEV-SNP is active then set the page state of the specified virtual > + address range. This should be called in SEC and PEI phases only. > + > + @param[in] BaseAddress Base address > + @param[in] NumPages Number of pages starting from the = base > address > + > +**/ > +VOID > +EFIAPI > +MemEncryptSevSnpValidateSystemRam ( > + IN PHYSICAL_ADDRESS BaseAddress, > + IN UINTN NumPages > + ) > +{ > + SevSnpValidateSystemRam (BaseAddress, NumPages); > +} > diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/SnpPageStateChange.h > b/OvmfPkg/Library/BaseMemEncryptSevLib/SnpPageStateChange.h > new file mode 100644 > index 0000000000..3040930999 > --- /dev/null > +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/SnpPageStateChange.h > @@ -0,0 +1,37 @@ > +/** @file > + > + SEV-SNP Page Validation functions. > + > + Copyright (c) 2020 - 2021, AMD Incorporated. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef SNP_PAGE_STATE_INTERNAL_H_ > +#define SNP_PAGE_STATE_INTERNAL_H_ > + > +// > +// SEV-SNP Page states > +// > +typedef enum { > + SevSnpPagePrivate, > + SevSnpPageShared, > + > +} SEV_SNP_PAGE_STATE; > + > +VOID > +SevSnpValidateSystemRam ( > + IN EFI_PHYSICAL_ADDRESS BaseAddress, > + IN UINTN NumPages > + ); > + > +VOID > +SetPageStateInternal ( > + IN EFI_PHYSICAL_ADDRESS BaseAddress, > + IN UINTN NumPages, > + IN SEV_SNP_PAGE_STATE State, > + IN BOOLEAN UseLargeEntry > + ); > + > +#endif > diff --git > a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecSnpSystemRamValidate.c > b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecSnpSystemRamValidate.c > new file mode 100644 > index 0000000000..915706aad0 > --- /dev/null > +++ > b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecSnpSystemRamValidate.c > @@ -0,0 +1,23 @@ > +/** @file > + > + SEV-SNP Page Validation functions. > + > + Copyright (c) 2020 - 2021, AMD Incorporated. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > +#include > + > +#include "../SnpPageStateChange.h" > + > +VOID > +SevSnpValidateSystemRam ( > + IN EFI_PHYSICAL_ADDRESS BaseAddress, > + IN UINTN NumPages > + ) > +{ > + SetPageStateInternal (BaseAddress, NumPages, SevSnpPagePrivate, TRUE); > +} > diff --git > a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c > b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c > new file mode 100644 > index 0000000000..5a34db33fe > --- /dev/null > +++ > b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SnpPageStateChangeInternal.c > @@ -0,0 +1,254 @@ > +/** @file > + > + SEV-SNP Page Validation functions. > + > + Copyright (c) 2020 - 2021, AMD Incorporated. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > + > +#include "../SnpPageStateChange.h" > + > +#define IS_ALIGNED(x, y) ((((x) & (y - 1)) =3D=3D 0)) > +#define PAGES_PER_LARGE_ENTRY 512 > +#define EFI_LARGE_PAGE (EFI_PAGE_SIZE * PAGES_PER_LARGE_ENTRY) > + > +STATIC > +UINTN > +MemoryStateToGhcbOp ( > + IN SEV_SNP_PAGE_STATE State > + ) > +{ > + UINTN Cmd; > + > + switch (State) { > + case SevSnpPageShared: Cmd =3D SNP_PAGE_STATE_SHARED; break; > + case SevSnpPagePrivate: Cmd =3D SNP_PAGE_STATE_PRIVATE; break; > + default: ASSERT(0); > + } > + > + return Cmd; > +} > + > +STATIC > +VOID > +SnpPageStateFailureTerminate ( > + VOID > + ) > +{ > + MSR_SEV_ES_GHCB_REGISTER Msr; > + > + // > + // Use the GHCB MSR Protocol to request termination by the hypervisor > + // > + Msr.GhcbPhysicalAddress =3D 0; > + Msr.GhcbTerminate.Function =3D GHCB_INFO_TERMINATE_REQUEST; > + Msr.GhcbTerminate.ReasonCodeSet =3D GHCB_TERMINATE_GHCB; > + Msr.GhcbTerminate.ReasonCode =3D GHCB_TERMINATE_GHCB_GENERAL; > + AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress); > + > + AsmVmgExit (); > + > + ASSERT (FALSE); > + CpuDeadLoop (); > +} > + > +STATIC > +UINTN > +IssuePvalidate ( > + IN UINTN Address, > + IN UINTN RmpPageSize, > + IN BOOLEAN Validate > + ) > +{ > + IA32_EFLAGS32 EFlags; > + UINTN Ret; > + > + Ret =3D AsmPvalidate (RmpPageSize, Validate, Address, &EFlags); > + > + // > + // Check the rFlags.CF to verify that PVALIDATE updated the RMP > + // entry. If there was a no change in the RMP entry then we are > + // either double validating or invalidating the memory. This can > + // lead to a security compromise. > + // > + if (EFlags.Bits.CF) { > + DEBUG ((DEBUG_ERROR, "%a:%a: Double %a detected for address 0x%Lx\n"= , > + gEfiCallerBaseName, > + __FUNCTION__, > + Validate ? "Validate" : "Invalidate", > + Address)); > + SnpPageStateFailureTerminate (); > + } > + > + return Ret; > +} > + > +/** > + This function issues the PVALIDATE instruction to validate or invalidat= e the > memory > + range specified. If PVALIDATE returns size mismatch then it tries valid= ating > with > + smaller page size. > + > + */ > +STATIC > +VOID > +PvalidateRange ( > + IN SNP_PAGE_STATE_CHANGE_INFO *Info, > + IN UINTN StartIndex, > + IN UINTN EndIndex, > + IN BOOLEAN Validate > + ) > +{ > + UINTN Address, RmpPageSize, Ret, i; > + > + for (; StartIndex < EndIndex; StartIndex++) { > + Address =3D Info->Entry[StartIndex].GuestFrameNumber << EFI_PAGE_SHI= FT; > + RmpPageSize =3D Info->Entry[StartIndex].PageSize; > + > + Ret =3D IssuePvalidate (Address, RmpPageSize, Validate); > + > + // > + // If we fail to validate due to size mismatch then try with the > + // smaller page size. This senario will occur if the backing page in > + // the RMP entry is 4K and we are validating it as a 2MB. > + // > + if ((Ret =3D=3D PVALIDATE_RET_FAIL_SIZEMISMATCH) && > + (RmpPageSize =3D=3D PVALIDATE_PAGE_SIZE_2M)) { > + for (i =3D 0; i < PAGES_PER_LARGE_ENTRY; i++) { > + > + Ret =3D IssuePvalidate (Address, PVALIDATE_PAGE_SIZE_4K, Validat= e); > + if (Ret) { > + break; > + } > + > + Address =3D Address + EFI_PAGE_SIZE; > + } > + } > + > + if (Ret) { > + DEBUG ((DEBUG_ERROR, "%a:%a: Failed to %a address 0x%Lx Error > code %d\n", > + gEfiCallerBaseName, > + __FUNCTION__, > + Validate ? "Validate" : "Invalidate", > + Address, > + Ret)); > + SnpPageStateFailureTerminate (); > + } > + } > +} > + > +/** > + The function is used to set the page state when SEV-SNP is active. The = page > state > + transition consist of changing the page ownership in the RMP table, and= using > the > + PVALIDATE instruction to update the Validated bit in RMP table. > + > + When the UseLargeEntry is set to TRUE, then use the large RMP entry. > + */ > +VOID > +SetPageStateInternal ( > + IN EFI_PHYSICAL_ADDRESS BaseAddress, > + IN UINTN NumPages, > + IN SEV_SNP_PAGE_STATE State, > + IN BOOLEAN UseLargeEntry > + ) > +{ > + EFI_STATUS Status; > + GHCB *Ghcb; > + EFI_PHYSICAL_ADDRESS NextAddress, EndAddress; > + MSR_SEV_ES_GHCB_REGISTER Msr; > + BOOLEAN InterruptState; > + SNP_PAGE_STATE_CHANGE_INFO *Info; > + UINTN i, RmpPageSize; > + > + Msr.GhcbPhysicalAddress =3D AsmReadMsr64 (MSR_SEV_ES_GHCB); > + Ghcb =3D Msr.Ghcb; > + > + EndAddress =3D BaseAddress + EFI_PAGES_TO_SIZE (NumPages); > + > + DEBUG ((DEBUG_VERBOSE, "%a:%a Address 0x%Lx - 0x%Lx State =3D %a > LargeEntry =3D %d\n", > + gEfiCallerBaseName, > + __FUNCTION__, > + BaseAddress, > + EndAddress, > + State =3D=3D SevSnpPageShared ? "Shared" : "Private", > + UseLargeEntry)); > + > + for (; BaseAddress < EndAddress; BaseAddress =3D NextAddress) { > + > + // > + // Initialize the GHCB and setup scratch sw to point to shared buffe= r. > + // > + VmgInit (Ghcb, &InterruptState); > + Info =3D (SNP_PAGE_STATE_CHANGE_INFO *) Ghcb->SharedBuffer; > + > + SetMem (Info, sizeof (*Info), 0); > + > + // > + // Build page state change buffer > + // > + for (i =3D 0; (EndAddress > BaseAddress) && i < SNP_PAGE_STATE_MAX_E= NTRY; > + BaseAddress =3D NextAddress, i++) { > + // > + // Is this a 2MB aligned page? Check if we can use the Large RMP e= ntry. > + // > + if (UseLargeEntry && > + IS_ALIGNED (BaseAddress, EFI_LARGE_PAGE) && > + ((EndAddress - BaseAddress) >> EFI_PAGE_SHIFT) >=3D > PAGES_PER_LARGE_ENTRY) { > + RmpPageSize =3D PVALIDATE_PAGE_SIZE_2M; > + NextAddress =3D BaseAddress + EFI_LARGE_PAGE; > + } else { > + RmpPageSize =3D PVALIDATE_PAGE_SIZE_4K; > + NextAddress =3D BaseAddress + EFI_PAGE_SIZE; > + } > + > + Info->Entry[i].GuestFrameNumber =3D BaseAddress >> EFI_PAGE_SHIFT; > + Info->Entry[i].PageSize =3D RmpPageSize; > + Info->Entry[i].Op =3D MemoryStateToGhcbOp (State); > + Info->Entry[i].CurrentPage =3D 0; > + } > + > + Info->Header.CurrentEntry =3D 0; > + Info->Header.EndEntry =3D i - 1; > + > + // > + // If the request page state change is shared then invalidate the pa= ges before > + // adding the page in the RMP table. > + // > + if (State =3D=3D SevSnpPageShared) { > + PvalidateRange (Info, 0, i, FALSE); > + } > + > + // > + // Issue the VMGEXIT and retry if hypervisor failed to process all t= he entries. > + // > + Ghcb->SaveArea.SwScratch =3D (UINT64) Ghcb->SharedBuffer; > + VmgSetOffsetValid (Ghcb, GhcbSwScratch); > + while (Info->Header.CurrentEntry <=3D Info->Header.EndEntry) { > + Status =3D VmgExit (Ghcb, SVM_EXIT_SNP_PAGE_STATE_CHANGE, 0, 0); > + if (EFI_ERROR (Status)) { > + SnpPageStateFailureTerminate (); > + } > + } > + > + // > + // If the request page state change is shared then invalidate the pa= ges before > + // adding the page in the RMP table. > + // > + if (State =3D=3D SevSnpPagePrivate) { > + PvalidateRange (Info, 0, i, TRUE); > + } > + > + VmgDone (Ghcb, InterruptState); > + } > +} > -- > 2.17.1