public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Gerd Hoffmann" <kraxel@redhat.com>
To: devel@edk2.groups.io
Cc: Jordan Justen <jordan.l.justen@intel.com>,
	Gerd Hoffmann <kraxel@redhat.com>,
	Pawel Polawski <ppolawsk@redhat.com>,
	Jiewen Yao <jiewen.yao@intel.com>,
	Oliver Steffen <osteffen@redhat.com>,
	Ard Biesheuvel <ardb+tianocore@kernel.org>
Subject: [PATCH v2 1/4] OvmfPkg/PlatformInitLib: qemu cpuid physbits detection
Date: Tue,  4 Oct 2022 15:47:25 +0200	[thread overview]
Message-ID: <20221004134728.55499-2-kraxel@redhat.com> (raw)
In-Reply-To: <20221004134728.55499-1-kraxel@redhat.com>

Add some qemu specific quirks to PlatformAddressWidthFromCpuid()
to figure whenever the PhysBits value returned by CPUID is
something real we can work with or not.

See the source code comment for details on the logic.

Also apply some limits to the address space we are going to use:
 * Place a hard cap at 47 PhysBits (128 TB) to avoid using addresses
   which require 5-level paging support.
 * Cap at 40 PhysBits (1 TB) in case the CPU has no support for
   gigabyte pages, to avoid excessive amounts of pages being
   used for page tables.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 OvmfPkg/Library/PlatformInitLib/MemDetect.c | 102 ++++++++++++++++----
 1 file changed, 84 insertions(+), 18 deletions(-)

diff --git a/OvmfPkg/Library/PlatformInitLib/MemDetect.c b/OvmfPkg/Library/PlatformInitLib/MemDetect.c
index d1a4f4b20791..143a01ceb01e 100644
--- a/OvmfPkg/Library/PlatformInitLib/MemDetect.c
+++ b/OvmfPkg/Library/PlatformInitLib/MemDetect.c
@@ -503,39 +503,105 @@ PlatformGetFirstNonAddress (
 }
 
 /*
- * Use CPUID to figure physical address width.  Does *not* work
- * reliable on qemu.  For historical reasons qemu returns phys-bits=40
- * even in case the host machine supports less than that.
- *
- * qemu has a cpu property (host-phys-bits={on,off}) to change that
- * and make sure guest phys-bits are not larger than host phys-bits.,
- * but it is off by default.  Exception: microvm machine type
- * hard-wires that property to on.
+ * Use CPUID to figure physical address width.
+ *
+ * Does *not* work reliable on qemu.  For historical reasons qemu
+ * returns phys-bits=40 by default even in case the host machine
+ * supports less than that.
+ *
+ * So we apply the following rules (which can be enabled/disabled
+ * using the QemuQuirk parameter) to figure whenever we can work with
+ * the returned physical address width or not:
+ *
+ *   (1) If it is 41 or higher consider it valid.
+ *   (2) If it is 40 or lower consider it valid in case it matches a
+ *       known-good value for the CPU vendor, which is:
+ *         ->  36 or 39 for Intel
+ *         ->  40 for AMD
+ *   (3) Otherwise consider it invalid.
+ *
+ * Recommendation: Run qemu with host-phys-bits=on.  That will make
+ * sure guest phys-bits is not larger than host phys-bits.  Some
+ * distro builds do that by default.
  */
 VOID
 EFIAPI
 PlatformAddressWidthFromCpuid (
-  IN OUT EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
+  IN OUT EFI_HOB_PLATFORM_INFO  *PlatformInfoHob,
+  IN     BOOLEAN                QemuQuirk
   )
 {
-  UINT32  RegEax;
+  UINT32   RegEax, RegEbx, RegEcx, RegEdx, Max;
+  UINT8    PhysBits;
+  CHAR8    Signature[13] = { 0 };
+  BOOLEAN  Valid         = FALSE;
+  BOOLEAN  Page1GSupport = FALSE;
 
-  AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
-  if (RegEax >= 0x80000008) {
+  AsmCpuid (0x80000000, &RegEax, &RegEbx, &RegEcx, &RegEdx);
+  *(UINT32 *)(Signature + 0) = RegEbx;
+  *(UINT32 *)(Signature + 4) = RegEdx;
+  *(UINT32 *)(Signature + 8) = RegEcx;
+  Max                        = RegEax;
+
+  if (Max >= 0x80000001) {
+    AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
+    if ((RegEdx & BIT26) != 0) {
+      Page1GSupport = TRUE;
+    }
+  }
+
+  if (Max >= 0x80000008) {
     AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
-    PlatformInfoHob->PhysMemAddressWidth = (UINT8)RegEax;
+    PhysBits = (UINT8)RegEax;
   } else {
-    PlatformInfoHob->PhysMemAddressWidth = 36;
+    PhysBits = 36;
   }
 
-  PlatformInfoHob->FirstNonAddress = LShiftU64 (1, PlatformInfoHob->PhysMemAddressWidth);
+  if (!QemuQuirk) {
+    Valid = TRUE;
+  } else if (PhysBits >= 41) {
+    Valid = TRUE;
+  } else if (AsciiStrCmp (Signature, "GenuineIntel") == 0) {
+    if ((PhysBits == 36) || (PhysBits == 39)) {
+      Valid = TRUE;
+    }
+  } else if (AsciiStrCmp (Signature, "AuthenticAMD") == 0) {
+    if (PhysBits == 40) {
+      Valid = TRUE;
+    }
+  }
 
   DEBUG ((
     DEBUG_INFO,
-    "%a: cpuid: phys-bits is %d\n",
+    "%a: Signature: '%a', PhysBits: %d, QemuQuirk: %a, Valid: %a\n",
     __FUNCTION__,
-    PlatformInfoHob->PhysMemAddressWidth
+    Signature,
+    PhysBits,
+    QemuQuirk ? "On" : "Off",
+    Valid ? "Yes" : "No"
     ));
+
+  if (Valid) {
+    if (PhysBits > 47) {
+      /*
+       * Avoid 5-level paging altogether for now, which limits
+       * PhysBits to 48.  Also avoid using address bit 48, due to sign
+       * extension we can't identity-map these addresses (and lots of
+       * places in edk2 assume we have everything identity-mapped).
+       * So the actual limit is 47.
+       */
+      DEBUG ((DEBUG_INFO, "%a: limit PhysBits to 47 (avoid 5-level paging)\n", __func__));
+      PhysBits = 47;
+    }
+
+    if (!Page1GSupport && (PhysBits > 40)) {
+      DEBUG ((DEBUG_INFO, "%a: limit PhysBits to 40 (no 1G pages available)\n", __func__));
+      PhysBits = 40;
+    }
+
+    PlatformInfoHob->PhysMemAddressWidth = PhysBits;
+    PlatformInfoHob->FirstNonAddress     = LShiftU64 (1, PlatformInfoHob->PhysMemAddressWidth);
+  }
 }
 
 /**
@@ -672,7 +738,7 @@ PlatformAddressWidthInitialization (
   EFI_STATUS  Status;
 
   if (PlatformInfoHob->HostBridgeDevId == 0xffff /* microvm */) {
-    PlatformAddressWidthFromCpuid (PlatformInfoHob);
+    PlatformAddressWidthFromCpuid (PlatformInfoHob, FALSE);
     return;
   }
 
-- 
2.37.3


  reply	other threads:[~2022-10-04 13:47 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-04 13:47 [PATCH v2 0/4] OvmfPkg: make better use of physical address space Gerd Hoffmann
2022-10-04 13:47 ` Gerd Hoffmann [this message]
2022-10-04 13:47 ` [PATCH v2 2/4] OvmfPkg/PlatformInitLib: detect " Gerd Hoffmann
2023-03-16 13:58   ` f.ebner
2023-03-16 14:37     ` Gerd Hoffmann
2023-03-17 11:34       ` [edk2-devel] " Fiona Ebner
2023-03-17 14:01     ` Gerd Hoffmann
2023-03-20 14:20       ` Fiona Ebner
2023-03-20 15:58         ` Gerd Hoffmann
2022-10-04 13:47 ` [PATCH v2 3/4] OvmfPkg/PlatformInitLib: dynamic mmio window size Gerd Hoffmann
2023-03-15  8:54   ` [edk2-devel] " joeyli
2023-03-15  9:28     ` Gerd Hoffmann
2023-05-16 14:00   ` Fiona Ebner
2023-05-17  5:59     ` [edk2-devel] " Gerd Hoffmann
2023-05-17 13:38       ` Fiona Ebner
2023-05-22 11:12         ` Gerd Hoffmann
2023-05-22 13:36           ` Fiona Ebner
2022-10-04 13:47 ` [PATCH v2 4/4] OvmfPkg/PciHotPlugInitDxe: reserve more mmio space Gerd Hoffmann
2022-10-04 15:57   ` Laszlo Ersek
2022-10-05  5:01     ` Gerd Hoffmann
2022-10-06  8:50       ` Laszlo Ersek
2022-10-07 21:49 ` [edk2-devel] [PATCH v2 0/4] OvmfPkg: make better use of physical address space Ard Biesheuvel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221004134728.55499-2-kraxel@redhat.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox