Add support for reading the TTM page limit from an EFI variable,
allowing BIOS firmware or users to set persistent memory limits
via EFI. This enables platform-specific GPU memory constraints
without kernel command line or module parameter modifications.

The EFI variable TTMPageLimit (GUID 8be4df61-93ca-11ec-b909...)
is checked during initialization with the following priority:
  1. Module parameter (ttm.pages_limit)
  2. EFI variable (TTMPageLimit)
  3. Auto-calculated default (50% of system RAM)

If the EFI variable is not found or contains invalid data, the
system gracefully falls back to auto-calculation.

Assisted-by: Claude Opus 4.6
Signed-off-by: Mario Limonciello <[email protected]>
---
 drivers/gpu/drm/ttm/ttm_tt.c | 95 +++++++++++++++++++++++++++++++++++-
 1 file changed, 93 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index b645a18181843..a5641588c4f22 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -49,6 +49,11 @@
 #include "ttm_module.h"
 #include "ttm_pool_internal.h"
 
+#include <linux/sizes.h>
+#ifdef CONFIG_EFI
+#include <linux/efi.h>
+#endif
+
 static unsigned long ttm_pages_limit;
 
 MODULE_PARM_DESC(pages_limit, "Limit for the allocated pages");
@@ -464,6 +469,79 @@ DEFINE_SHOW_ATTRIBUTE(ttm_tt_debugfs_shrink);
 
 #endif
 
+#ifdef CONFIG_EFI
+/*
+ * EFI variable GUID for TTM page limit configuration
+ * GUID: 8be4df61-93ca-11ec-b909-0800200c9a66
+ */
+static const efi_guid_t TTM_EFI_GUID =
+       EFI_GUID(0x8be4df61, 0x93ca, 0x11ec, 0xb9, 0x09, 0x08, 0x00, 0x20, 
0x0c, 0x9a, 0x66);
+
+/*
+ * ttm_read_efi_pages_limit - Read TTM page limit from EFI variable
+ *
+ * Attempts to read the TTMPageLimit EFI variable to get a platform-specific
+ * page limit configuration. This allows BIOS firmware or users
+ * to set persistent GPU memory limits without kernel command line 
modification.
+ *
+ * Returns: Page count on success, 0 on any error (triggers auto-calculation)
+ */
+static unsigned long ttm_read_efi_pages_limit(void)
+{
+       efi_char16_t efi_name[] = L"TTMPageLimit";
+       unsigned long size = sizeof(u64);
+       struct sysinfo si;
+       efi_status_t status;
+       u64 page_limit;
+
+       if (!efi_enabled(EFI_BOOT))
+               return 0;
+
+       if (efivar_lock())
+               return 0;
+
+       status = efivar_get_variable(efi_name, (efi_guid_t *)&TTM_EFI_GUID,
+                                    NULL, &size, &page_limit);
+       efivar_unlock();
+
+       if (status == EFI_NOT_FOUND) {
+               pr_debug("TTMPageLimit EFI variable not found\n");
+               return 0;
+       }
+
+       if (status != EFI_SUCCESS) {
+               pr_debug("Failed to read TTMPageLimit EFI variable: %d\n",
+                        efi_status_to_err(status));
+               return 0;
+       }
+
+       if (size != sizeof(u64)) {
+               pr_warn("Invalid TTMPageLimit size: %lu bytes (expected %zu)\n",
+                       size, sizeof(u64));
+               return 0;
+       }
+
+       page_limit = le64_to_cpu(page_limit);
+
+       if (page_limit == 0)
+               return 0;
+
+       si_meminfo(&si);
+       if (page_limit > si.totalram) {
+               pr_warn("TTMPageLimit (%llu pages) exceeds system RAM (%lu 
pages), capping to system RAM\n",
+                       page_limit, si.totalram);
+               page_limit = si.totalram;
+       }
+
+       pr_info("Using TTMPageLimit from EFI: %llu pages\n", page_limit);
+       return (unsigned long)page_limit;
+}
+#else
+static unsigned long ttm_read_efi_pages_limit(void)
+{
+       return 0;
+}
+#endif /* CONFIG_EFI */
 
 /*
  * ttm_tt_mgr_init - register with the MM shrinker
@@ -472,13 +550,26 @@ DEFINE_SHOW_ATTRIBUTE(ttm_tt_debugfs_shrink);
  */
 void ttm_tt_mgr_init(unsigned long num_pages, unsigned long num_dma32_pages)
 {
+       unsigned long efi_limit;
+
 #ifdef CONFIG_DEBUG_FS
        debugfs_create_file("tt_shrink", 0400, ttm_debugfs_root, NULL,
                            &ttm_tt_debugfs_shrink_fops);
 #endif
 
-       if (!ttm_pages_limit)
-               ttm_pages_limit = num_pages;
+       /*
+        * Priority chain for pages_limit:
+        * 1. Module parameter (ttm.pages_limit) - highest priority
+        * 2. EFI variable (TTMPageLimit) - middle priority
+        * 3. Auto-calculation (50% of system RAM) - fallback
+        */
+       if (!ttm_pages_limit) {
+               efi_limit = ttm_read_efi_pages_limit();
+               if (efi_limit > 0)
+                       ttm_pages_limit = efi_limit;
+               else
+                       ttm_pages_limit = num_pages;
+       }
 
        if (!ttm_dma32_pages_limit)
                ttm_dma32_pages_limit = num_dma32_pages;
-- 
2.53.0

Reply via email to