[PATCH 04/14] drm/amdgpu: add amdgpu_discovery_get_mem_reserved_info_table

Alex Deucher <[email protected]>
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
From: Feifei Xu <[email protected]>

Add interface to query the optional MEM_RESERVED_INFO table:

  - introduce amdgpu_discovery_get_mem_reserved_info_table() which
    resolves the table from the discovery binary and caches the pointer
    in adev->discovery.mem_reserved_table so subsequent lookups are
    cheap;
  - invoke it once at init time. Missing/invalid table is non-fatal.

Signed-off-by: Feifei Xu <[email protected]>
Reviewed-by: Hawking Zhang <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 55 ++++++++++++++++++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h |  4 ++
 2 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
index af1404ae2b70c..4d55933f033cc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
@@ -684,6 +684,15 @@ static int amdgpu_discovery_table_check(struct amdgpu_device *adev,
 		check_table = false;
 		break;
 	}
+	case MEM_RESERVED_INFO: {
+		struct mem_reserved_info_header *mrhdr =
+			(struct mem_reserved_info_header *)(discovery_bin + offset);
+		act_val = le32_to_cpu(mrhdr->signature);
+		exp_val = MEM_RSV_TABLE_SIGNATURE;
+		table_size = le32_to_cpu(mrhdr->size);
+		table_name = "mem_reserved table";
+		break;
+	}
 	default:
 		dev_err(adev->dev, "invalid ip discovery table id %d specified\n", table_id);
 		check_table = false;
@@ -772,12 +781,17 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
 		goto out;
 	}
 
-	for (table_id = 0; table_id <= MALL_INFO; table_id++) {
+	for (table_id = 0; table_id < TOTAL_TABLES; table_id++) {
 		r = amdgpu_discovery_table_check(adev, discovery_bin, table_id);
 		if (r)
 			goto out;
 	}
 
+	/*
+	 * Resolve the MEM_RESERVED_INFO table once at init time. The table
+	 * is optional, so missing it is not a fatal error.
+	 */
+	amdgpu_discovery_get_mem_reserved_info_table(adev);
 	return 0;
 
 out:
@@ -796,6 +810,8 @@ void amdgpu_discovery_fini(struct amdgpu_device *adev)
 
 	kfree(adev->discovery.bin);
 	adev->discovery.bin = NULL;
+	/* Cached pointer lives inside discovery.bin; drop it to avoid UAF. */
+	adev->discovery.mem_reserved_table = NULL;
 }
 
 static int amdgpu_discovery_validate_ip(struct amdgpu_device *adev,
@@ -2375,6 +2391,43 @@ int amdgpu_discovery_get_nps_info(struct amdgpu_device *adev,
 	return 0;
 }
 
+/*
+ * Resolve the MEM_RESERVED_INFO table from the IP discovery binary and
+ * cache it in adev->discovery.mem_reserved_table.
+ * Return: 0 on success, -ENOENT/-EINVAL if the table unavailable.
+ */
+int amdgpu_discovery_get_mem_reserved_info_table(struct amdgpu_device *adev)
+{
+	uint8_t *discovery_bin = adev->discovery.bin;
+	struct table_info *info;
+
+	/* If already queried, do not query again. */
+	if (adev->discovery.mem_reserved_table)
+		return 0;
+
+	if (!discovery_bin) {
+		dev_err(adev->dev, "ip discovery uninitialized\n");
+		return -ENOENT;
+	}
+
+	if (amdgpu_discovery_get_table_info(adev, &info, MEM_RESERVED_INFO)) {
+		dev_dbg(adev->dev, "MEM_RESERVED_INFO table entry not present\n");
+		return -EINVAL;
+	}
+
+	if (!le16_to_cpu(info->offset)) {
+		dev_dbg(adev->dev, "MEM_RESERVED_INFO table offset is 0, invalid!\n");
+		return -EINVAL;
+	}
+
+	/* Cache for subsequent lookups. */
+	adev->discovery.mem_reserved_table =
+		(struct mem_reserved_info_table_v1_0 *)(discovery_bin + le16_to_cpu(info->offset));
+
+	dev_dbg(adev->dev, "MEM_RESERVED_INFO table exist\n");
+	return 0;
+}
+
 static int amdgpu_discovery_set_common_ip_blocks(struct amdgpu_device *adev)
 {
 	/* what IP to use for this? */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h
index 5b2b16f68576c..070b404c1944c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h
@@ -25,6 +25,7 @@
 #define __AMDGPU_DISCOVERY__
 
 #include <linux/debugfs.h>
+#include "discovery.h"
 
 #define DISCOVERY_TMR_SIZE      (10 << 10)
 #define DISCOVERY_TMR_OFFSET    (64 << 10)
@@ -39,6 +40,7 @@ struct amdgpu_discovery_info {
 	uint32_t size;
 	uint8_t *bin;
 	bool reserve_tmr;
+	struct mem_reserved_info_table_v1_0 *mem_reserved_table;
 };
 
 void amdgpu_discovery_sysfs_fini(struct amdgpu_device *adev);
@@ -59,4 +61,6 @@ int amdgpu_discovery_sysfs_early_init(struct amdgpu_device *adev,
 				       struct pci_dev *pdev);
 void amdgpu_discovery_sysfs_early_fini(struct pci_dev *pdev);
 
+int amdgpu_discovery_get_mem_reserved_info_table(struct amdgpu_device *adev);
+
 #endif /* __AMDGPU_DISCOVERY__ */
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.