[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