mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 09:20:13 -04:00
drm/amdgpu/ras: Add address sanity check for uniras
Add address sanity check for uniras Signed-off-by: Ce Sun <cesun102@amd.com> Reviewed-by: Tao Zhou <tao.zhou1@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
#include <linux/mempool.h>
|
||||
#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) \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user