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