From a234d4a543187f2d94a2ecd3369748dc071c655c Mon Sep 17 00:00:00 2001 From: Ce Sun Date: Thu, 11 Jun 2026 15:38:46 +0800 Subject: [PATCH] drm/amdgpu/ras: Add address sanity check for uniras Add address sanity check for uniras Signed-off-by: Ce Sun Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- .../gpu/drm/amd/ras/ras_mgr/amdgpu_ras_cmd.c | 3 -- .../gpu/drm/amd/ras/ras_mgr/amdgpu_ras_sys.c | 19 +++++++++++ drivers/gpu/drm/amd/ras/ras_mgr/ras_sys.h | 3 ++ drivers/gpu/drm/amd/ras/rascore/ras.h | 2 ++ drivers/gpu/drm/amd/ras/rascore/ras_core.c | 10 ++++++ drivers/gpu/drm/amd/ras/rascore/ras_umc.c | 32 ++++++++++++++++--- drivers/gpu/drm/amd/ras/rascore/ras_umc.h | 6 ++++ 7 files changed, 68 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_cmd.c b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_cmd.c index 658bf3fdb66b..bfbfdffbfbe6 100644 --- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_cmd.c +++ b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_cmd.c @@ -30,9 +30,6 @@ #include "amdgpu_ras_mgr.h" #include "amdgpu_virt_ras_cmd.h" -/* inject address is 52 bits */ -#define RAS_UMC_INJECT_ADDR_LIMIT (0x1ULL << 52) - #define AMDGPU_RAS_TYPE_RASCORE 0x1 #define AMDGPU_RAS_TYPE_AMDGPU 0x2 #define AMDGPU_RAS_TYPE_VF 0x3 diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_sys.c b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_sys.c index 7d728e523604..e4444798bc73 100644 --- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_sys.c +++ b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_sys.c @@ -267,6 +267,24 @@ static int amdgpu_ras_sys_put_gpu_mem(struct ras_core_context *ras_core, return 0; } +static int amdgpu_ras_sys_check_address_sanity(struct ras_core_context *ras_core, + uint64_t addr) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)ras_core->dev; + + if ((addr >= adev->gmc.mc_vram_size && + adev->gmc.mc_vram_size) || + (addr >= RAS_UMC_INJECT_ADDR_LIMIT)) + return -EINVAL; + + if (addr >= adev->gmc.real_vram_size) { + RAS_DEV_WARN(ras_core->dev, "Recorded address out of range: 0x%llx!\n", addr); + return -EINVAL; + } + + return 0; +} + const struct ras_sys_func amdgpu_ras_sys_fn = { .ras_notifier = amdgpu_ras_sys_event_notifier, .get_utc_second_timestamp = amdgpu_ras_sys_get_utc_second_timestamp, @@ -277,4 +295,5 @@ const struct ras_sys_func amdgpu_ras_sys_fn = { .detect_ras_interrupt = amdgpu_ras_sys_detect_ras_interrupt, .get_gpu_mem = amdgpu_ras_sys_get_gpu_mem, .put_gpu_mem = amdgpu_ras_sys_put_gpu_mem, + .check_address_sanity = amdgpu_ras_sys_check_address_sanity, }; diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/ras_sys.h b/drivers/gpu/drm/amd/ras/ras_mgr/ras_sys.h index f34dda7ce87b..2775c7bf41b7 100644 --- a/drivers/gpu/drm/amd/ras/ras_mgr/ras_sys.h +++ b/drivers/gpu/drm/amd/ras/ras_mgr/ras_sys.h @@ -30,6 +30,9 @@ #include #include "amdgpu.h" +/* inject address is 52 bits */ +#define RAS_UMC_INJECT_ADDR_LIMIT (0x1ULL << 52) + #define RAS_DEV_ERR(device, fmt, ...) \ do { \ if (device) \ diff --git a/drivers/gpu/drm/amd/ras/rascore/ras.h b/drivers/gpu/drm/amd/ras/rascore/ras.h index c059fcebaf00..5869bad978b0 100644 --- a/drivers/gpu/drm/amd/ras/rascore/ras.h +++ b/drivers/gpu/drm/amd/ras/rascore/ras.h @@ -231,6 +231,7 @@ struct ras_sys_func { enum gpu_mem_type mem_type, struct gpu_mem_block *gpu_mem); int (*put_gpu_mem)(struct ras_core_context *ras_core, enum gpu_mem_type mem_type, struct gpu_mem_block *gpu_mem); + int (*check_address_sanity)(struct ras_core_context *ras_core, uint64_t addr); }; struct ras_ecc_count { @@ -398,4 +399,5 @@ int ras_core_get_device_system_info(struct ras_core_context *ras_core, struct device_system_info *dev_info); int ras_core_convert_soc_pa_to_cur_nps_pages(struct ras_core_context *ras_core, uint64_t soc_pa, uint64_t *page_pfn, uint32_t max_pages); +int ras_core_check_address_sanity(struct ras_core_context *ras_core, uint64_t addr); #endif diff --git a/drivers/gpu/drm/amd/ras/rascore/ras_core.c b/drivers/gpu/drm/amd/ras/rascore/ras_core.c index 62d124a3eeac..2346918c7736 100644 --- a/drivers/gpu/drm/amd/ras/rascore/ras_core.c +++ b/drivers/gpu/drm/amd/ras/rascore/ras_core.c @@ -676,3 +676,13 @@ int ras_core_convert_soc_pa_to_cur_nps_pages(struct ras_core_context *ras_core, return count; } + +int ras_core_check_address_sanity(struct ras_core_context *ras_core, + uint64_t addr) +{ + if (ras_core && ras_core->sys_fn && + ras_core->sys_fn->check_address_sanity) + return ras_core->sys_fn->check_address_sanity(ras_core, addr); + + return 0; +} diff --git a/drivers/gpu/drm/amd/ras/rascore/ras_umc.c b/drivers/gpu/drm/amd/ras/rascore/ras_umc.c index f32ee2fecf53..e366fb97293e 100644 --- a/drivers/gpu/drm/amd/ras/rascore/ras_umc.c +++ b/drivers/gpu/drm/amd/ras/rascore/ras_umc.c @@ -406,7 +406,7 @@ static int ras_umc_update_eeprom_ram_data(struct ras_core_context *ras_core, struct ras_umc *ras_umc = &ras_core->ras_umc; struct eeprom_store_record *data = &ras_umc->umc_err_data.ram_data; uint64_t page_pfn[16]; - int count = 0, j; + int count = 0, i, j; if (!data->space_left && ras_umc_realloc_err_data_space(ras_core, data, 256)) { @@ -418,10 +418,23 @@ static int ras_umc_update_eeprom_ram_data(struct ras_core_context *ras_core, bps, bps->cur_nps, page_pfn, ARRAY_SIZE(page_pfn)); if (count > 0) { for (j = 0; j < count; j++) { + if (ras_core_check_address_sanity(ras_core, + page_pfn[j] << AMDGPU_GPU_PAGE_SHIFT)) { + + for (i = 0; i < data->count; i++) + if (page_pfn[j] == data->bps[i].cur_nps_retired_row_pfn) + break; + data->bps[data->count].cur_nps_retired_row_pfn = U64_MAX; + data->count++; + data->space_left--; + continue; + } + bps->cur_nps_retired_row_pfn = page_pfn[j]; memcpy(&data->bps[data->count], bps, sizeof(*data->bps)); data->count++; data->space_left--; + data->bad_page_num++; } } else { RAS_DEV_ERR(ras_core->dev, "Failed to convert record to nps pages!"); @@ -431,6 +444,14 @@ static int ras_umc_update_eeprom_ram_data(struct ras_core_context *ras_core, return 0; } +static void ras_umc_update_bad_pages(struct ras_core_context *ras_core) +{ + struct ras_umc *ras_umc = &ras_core->ras_umc; + struct eeprom_store_record *data = &ras_umc->umc_err_data.ram_data; + + data->bad_page_num_old = data->bad_page_num; +} + /* it deal with vram only. */ static int ras_umc_add_bad_pages(struct ras_core_context *ras_core, struct eeprom_umc_record *bps, @@ -506,6 +527,7 @@ int ras_umc_load_bad_pages(struct ras_core_context *ras_core) } else { ras_core->ras_umc.umc_err_data.last_retired_pfn = UMC_INV_MEM_PFN; ret = ras_umc_add_bad_pages(ras_core, bps, ras_num_recs, true); + ras_umc_update_bad_pages(ras_core); } kfree(bps); @@ -521,7 +543,8 @@ static int ras_umc_save_bad_pages(struct ras_core_context *ras_core) { struct ras_umc *ras_umc = &ras_core->ras_umc; struct eeprom_store_record *data = &ras_umc->umc_err_data.rom_data; - uint32_t eeprom_record_num; + struct eeprom_store_record *ram_data = &ras_umc->umc_err_data.ram_data; + uint32_t eeprom_record_num, logical_count = 0; int save_count; int ret = 0; @@ -534,6 +557,7 @@ static int ras_umc_save_bad_pages(struct ras_core_context *ras_core) eeprom_record_num = ras_eeprom_get_record_count(ras_core); mutex_lock(&ras_umc->umc_lock); save_count = data->count - eeprom_record_num; + logical_count = ram_data->bad_page_num - ram_data->bad_page_num_old; /* only new entries are saved */ if (save_count > 0) { if (ras_fw_eeprom_supported(ras_core)) @@ -547,8 +571,8 @@ static int ras_umc_save_bad_pages(struct ras_core_context *ras_core) ret = -EIO; goto exit; } - - RAS_DEV_INFO(ras_core->dev, "Saved %d pages to EEPROM table.\n", save_count); + ras_umc_update_bad_pages(ras_core); + RAS_DEV_INFO(ras_core->dev, "Saved %d pages to EEPROM table.\n", logical_count); } exit: diff --git a/drivers/gpu/drm/amd/ras/rascore/ras_umc.h b/drivers/gpu/drm/amd/ras/rascore/ras_umc.h index 237525b46b9b..ee7100f25f51 100644 --- a/drivers/gpu/drm/amd/ras/rascore/ras_umc.h +++ b/drivers/gpu/drm/amd/ras/rascore/ras_umc.h @@ -119,6 +119,12 @@ struct eeprom_store_record { int count; /* the space can place new entries */ int space_left; + /* logical bad page number */ + int bad_page_num; + /* the bad page number is ras_num_recs or + * ras_num_recs * retire_unit + */ + int bad_page_num_old; }; struct ras_umc_err_data {