From nobody Sat Dec 28 13:07:23 2024 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Authentication-Results: mx.zoho.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org; Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1496942035798178.2771462232813; Thu, 8 Jun 2017 10:13:55 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 7DC632094554F; Thu, 8 Jun 2017 10:12:35 -0700 (PDT) Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 16CD92095CC77 for ; Thu, 8 Jun 2017 10:12:34 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CD97680C38; Thu, 8 Jun 2017 17:13:42 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-116-122.phx2.redhat.com [10.3.116.122]) by smtp.corp.redhat.com (Postfix) with ESMTP id A74337F1CB; Thu, 8 Jun 2017 17:13:41 +0000 (UTC) X-Original-To: edk2-devel@lists.01.org DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com CD97680C38 Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=lersek@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com CD97680C38 From: Laszlo Ersek To: edk2-devel-01 Date: Thu, 8 Jun 2017 19:13:33 +0200 Message-Id: <20170608171333.17937-6-lersek@redhat.com> In-Reply-To: <20170608171333.17937-1-lersek@redhat.com> References: <20170608171333.17937-1-lersek@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Thu, 08 Jun 2017 17:13:43 +0000 (UTC) Subject: [edk2] [PATCH 5/5] OvmfPkg/Q35TsegSizeLib: recognize an extended TSEG when QEMU offers it 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: , Cc: Jordan Justen MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" This patch interfaces with the QEMU feature introduced in QEMU patch q35/mch: implement extended TSEG sizes Excerpt: > The q35 machine type currently lets the guest firmware select a 1MB, 2MB > or 8MB TSEG (basically, SMRAM) size. In edk2/OVMF, we use 8MB, but even > that is not enough when a lot of VCPUs (more than approx. 224) are > configured -- SMRAM footprint scales largely proportionally with VCPU > count. > > Introduce a new property for "mch" called "extended-tseg-mbytes", which > expresses (in megabytes) the user's choice of TSEG (SMRAM) size. > > Invent a new, QEMU-specific register in the config space of the DRAM > Controller, at offset 0x50, in order to allow guest firmware to query > the TSEG (SMRAM) size. > > According to Intel Document Number 316966-002, Table 5-1 "DRAM > Controller Register Address Map (D0:F0)": > > [...] > > Offsets 0x50 and 0x51 are not listed in Table 5-1. They are also not > part of the standard PCI config space header. And they precede the > capability list as well, which starts at 0xe0 for this device. > > When the guest writes value 0xffff to this register, the value that can > be read back is that of "mch.extended-tseg-mbytes" -- unless it remains > 0xffff. The guest is required to write 0xffff first (as opposed to a > read-only register) because PCI config space is generally not cleared on > QEMU reset, and after S3 resume or reboot, new guest firmware running on > old QEMU could read a guest OS-injected value from this register. > > After reading the available "extended" TSEG size, the guest firmware may > actually request that TSEG size by writing pattern 11b to the ESMRAMC > register's TSEG_SZ bit-field. (The Intel spec referenced above defines > only patterns 00b (1MB), 01b (2MB) and 10b (8MB); 11b is reserved.) > > On the QEMU command line, the value can be set with > > -global mch.extended-tseg-mbytes=3DN > > The default value for 2.10+ q35 machine types is 16. [...] Users are > responsible for choosing sensible TSEG sizes. > > On 2.9 and earlier q35 machine types, the default value is 0. This lets > the 11b bit pattern in ESMRAMC.TSEG_SZ, and the register at offset 0x50, > keep their original behavior. Relegate PcdQ35TsegMbytes to a fallback role, renaming it to PcdQ35TsegDefaultMbytes. Cc: Jordan Justen Ref: https://bugzilla.redhat.com/show_bug.cgi?id=3D1447027 Ref: https://lists.01.org/pipermail/edk2-devel/2017-May/010456.html Ref: http://mid.mail-archive.com/20170608161013.17920-1-lersek@redhat.com Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek --- OvmfPkg/OvmfPkg.dec | 8 ++-- OvmfPkg/Library/Q35TsegSizeLib/Q35TsegSizeLib.inf | 2 +- OvmfPkg/Include/IndustryStandard/Q35MchIch9.h | 4 ++ OvmfPkg/Library/Q35TsegSizeLib/Q35TsegSizeLib.c | 46 +++++++++++++++++++- 4 files changed, 55 insertions(+), 5 deletions(-) diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 7b9220369b95..2cae6a189d62 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -92,19 +92,21 @@ [PcdsFixedAtBuild] # MaxTarget and MaxLun, independently, should the host report higher va= lues, # so that scanning the number of devices given by their product is still # acceptably fast. gUefiOvmfPkgTokenSpaceGuid.PcdVirtioScsiMaxTargetLimit|31|UINT16|6 gUefiOvmfPkgTokenSpaceGuid.PcdVirtioScsiMaxLunLimit|7|UINT32|7 =20 ## The following setting controls how many megabytes we configure as TSE= G on - # Q35, for SMRAM purposes. Permitted values are: 1, 2, 8. Other values = cause - # undefined behavior. + # Q35, for SMRAM purposes, by default. Permitted values are: 1, 2, 8. O= ther + # values cause undefined behavior. # # This PCD is only consulted if PcdSmmSmramRequire is TRUE (see below). - gUefiOvmfPkgTokenSpaceGuid.PcdQ35TsegMbytes|8|UINT8|0x20 + # Furthermore, if QEMU offers an extended TSEG (as a Q35 extension), th= en + # this PCD is ignored. + gUefiOvmfPkgTokenSpaceGuid.PcdQ35TsegDefaultMbytes|8|UINT8|0x20 =20 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|= 0x8 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|= 0x9 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareBlockSize|0|UINT32|0xb gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageVariableBase|0x0|UINT32|= 0xc gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwSpareBase|0x0|UINT32|= 0xd diff --git a/OvmfPkg/Library/Q35TsegSizeLib/Q35TsegSizeLib.inf b/OvmfPkg/Li= brary/Q35TsegSizeLib/Q35TsegSizeLib.inf index 8f99e55b8c48..b7467d1a716c 100644 --- a/OvmfPkg/Library/Q35TsegSizeLib/Q35TsegSizeLib.inf +++ b/OvmfPkg/Library/Q35TsegSizeLib/Q35TsegSizeLib.inf @@ -40,8 +40,8 @@ [LibraryClasses] PcdLib PciLib =20 [FeaturePcd] gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire =20 [FixedPcd] - gUefiOvmfPkgTokenSpaceGuid.PcdQ35TsegMbytes + gUefiOvmfPkgTokenSpaceGuid.PcdQ35TsegDefaultMbytes diff --git a/OvmfPkg/Include/IndustryStandard/Q35MchIch9.h b/OvmfPkg/Includ= e/IndustryStandard/Q35MchIch9.h index f480455ae432..68485bec71f7 100644 --- a/OvmfPkg/Include/IndustryStandard/Q35MchIch9.h +++ b/OvmfPkg/Include/IndustryStandard/Q35MchIch9.h @@ -29,14 +29,17 @@ #define INTEL_Q35_MCH_DEVICE_ID 0x29C0 =20 // // B/D/F/Type: 0/0/0/PCI // #define DRAMC_REGISTER_Q35(Offset) PCI_LIB_ADDRESS (0, 0, 0, (Offset)) =20 +#define MCH_EXT_TSEG_MB 0x50 +#define MCH_EXT_TSEG_MB_QUERY 0xFFFF + #define MCH_GGC 0x52 #define MCH_GGC_IVD BIT1 =20 #define MCH_PCIEXBAR_LOW 0x60 #define MCH_PCIEXBAR_LOWMASK 0x0FFFFFFF #define MCH_PCIEXBAR_BUS_FF 0 #define MCH_PCIEXBAR_EN BIT0 @@ -50,14 +53,15 @@ =20 #define MCH_ESMRAMC 0x9E #define MCH_ESMRAMC_H_SMRAME BIT7 #define MCH_ESMRAMC_E_SMERR BIT6 #define MCH_ESMRAMC_SM_CACHE BIT5 #define MCH_ESMRAMC_SM_L1 BIT4 #define MCH_ESMRAMC_SM_L2 BIT3 +#define MCH_ESMRAMC_TSEG_EXT (BIT2 | BIT1) #define MCH_ESMRAMC_TSEG_8MB BIT2 #define MCH_ESMRAMC_TSEG_2MB BIT1 #define MCH_ESMRAMC_TSEG_1MB 0 #define MCH_ESMRAMC_TSEG_MASK (BIT2 | BIT1) #define MCH_ESMRAMC_T_EN BIT0 =20 #define MCH_GBSM 0xA4 diff --git a/OvmfPkg/Library/Q35TsegSizeLib/Q35TsegSizeLib.c b/OvmfPkg/Libr= ary/Q35TsegSizeLib/Q35TsegSizeLib.c index db57a8b308de..01054a093f51 100644 --- a/OvmfPkg/Library/Q35TsegSizeLib/Q35TsegSizeLib.c +++ b/OvmfPkg/Library/Q35TsegSizeLib/Q35TsegSizeLib.c @@ -17,14 +17,15 @@ #include #include #include #include =20 STATIC BOOLEAN mPreferencesInitialized; STATIC UINT8 mPreferredEsmramcTsegSzMask; +STATIC UINT16 mExtendedTsegMbytes; =20 /** Fetch the preferences into static variables that are going to be used by= the public functions of this library instance. =20 The Q35 board requirement documented on those interfaces is commonly enf= orced here. @@ -59,15 +60,49 @@ Q35TsegSizeGetPreferences ( )); ASSERT (FALSE); CpuDeadLoop (); } =20 mPreferencesInitialized =3D TRUE; =20 - switch (FixedPcdGet8 (PcdQ35TsegMbytes)) { + // + // Check if QEMU offers an extended TSEG. + // + // This can be seen from writing MCH_EXT_TSEG_MB_QUERY to the MCH_EXT_TS= EG_MB + // register, and reading back the register. + // + // On a QEMU machine type that does not offer an extended TSEG, the init= ial + // write overwrites whatever value a malicious guest OS may have placed = in + // the (unimplemented) register, before entering S3 or rebooting. + // Subsequently, the read returns MCH_EXT_TSEG_MB_QUERY unchanged. + // + // On a QEMU machine type that offers an extended TSEG, the initial write + // triggers an update to the register. Subsequently, the value read back + // (which is guaranteed to differ from MCH_EXT_TSEG_MB_QUERY) tells us t= he + // number of megabytes. + // + PciWrite16 (DRAMC_REGISTER_Q35 (MCH_EXT_TSEG_MB), MCH_EXT_TSEG_MB_QUERY); + mExtendedTsegMbytes =3D PciRead16 (DRAMC_REGISTER_Q35 (MCH_EXT_TSEG_MB)); + if (mExtendedTsegMbytes !=3D MCH_EXT_TSEG_MB_QUERY) { + DEBUG (( + DEBUG_INFO, + "%a: %a: QEMU offers an extended TSEG (%d MB)\n", + gEfiCallerBaseName, + __FUNCTION__, + mExtendedTsegMbytes + )); + + mPreferredEsmramcTsegSzMask =3D MCH_ESMRAMC_TSEG_EXT; + return; + } + + // + // Fall back to the default TSEG size otherwise. + // + switch (FixedPcdGet8 (PcdQ35TsegDefaultMbytes)) { case 1: mPreferredEsmramcTsegSzMask =3D MCH_ESMRAMC_TSEG_1MB; break; case 2: mPreferredEsmramcTsegSzMask =3D MCH_ESMRAMC_TSEG_2MB; break; case 8: @@ -161,14 +196,23 @@ Q35TsegSizeConvertEsmramcValToMbytes ( break; case MCH_ESMRAMC_TSEG_2MB: Mbytes =3D 2; break; case MCH_ESMRAMC_TSEG_8MB: Mbytes =3D 8; break; + case MCH_ESMRAMC_TSEG_EXT: + if (mExtendedTsegMbytes !=3D MCH_EXT_TSEG_MB_QUERY) { + Mbytes =3D mExtendedTsegMbytes; + break; + } + // + // Fall through otherwise -- QEMU didn't offer an extended TSEG, so th= is + // should never happen. + // default: DEBUG (( DEBUG_ERROR, "%a: %a: unknown TsegSizeBits=3D0x%02x\n", gEfiCallerBaseName, __FUNCTION__, TsegSizeBits --=20 2.9.3 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel