Skip to content

Commit 07009df

Browse files
Ellen Panalexdeucher
authored andcommitted
drm/amdgpu: Introduce SRIOV critical regions v2 during VF init
1. Introduced amdgpu_virt_init_critical_region during VF init. - VFs use init_data_header_offset and init_data_header_size_kb transmitted via PF2VF mailbox to fetch the offset of critical regions' offsets/sizes in VRAM and save to adev->virt.crit_region_offsets and adev->virt.crit_region_sizes_kb. Signed-off-by: Ellen Pan <yunru.pan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Lijo Lazar <lijo.lazar@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
1 parent 6d2191d commit 07009df

4 files changed

Lines changed: 220 additions & 0 deletions

File tree

drivers/gpu/drm/amd/amdgpu/amdgpu_device.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2782,6 +2782,10 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
27822782
r = amdgpu_virt_request_full_gpu(adev, true);
27832783
if (r)
27842784
return r;
2785+
2786+
r = amdgpu_virt_init_critical_region(adev);
2787+
if (r)
2788+
return r;
27852789
}
27862790

27872791
switch (adev->asic_type) {

drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,18 @@
4444
vf2pf_info->ucode_info[ucode].version = ver; \
4545
} while (0)
4646

47+
#define mmRCC_CONFIG_MEMSIZE 0xde3
48+
49+
const char *amdgpu_virt_dynamic_crit_table_name[] = {
50+
"IP DISCOVERY",
51+
"VBIOS IMG",
52+
"RAS TELEMETRY",
53+
"DATA EXCHANGE",
54+
"BAD PAGE INFO",
55+
"INIT HEADER",
56+
"LAST",
57+
};
58+
4759
bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev)
4860
{
4961
/* By now all MMIO pages except mailbox are blocked */
@@ -843,6 +855,168 @@ static void amdgpu_virt_init_ras(struct amdgpu_device *adev)
843855
adev->virt.ras.cper_rptr = 0;
844856
}
845857

858+
static uint8_t amdgpu_virt_crit_region_calc_checksum(uint8_t *buf_start, uint8_t *buf_end)
859+
{
860+
uint32_t sum = 0;
861+
862+
if (buf_start >= buf_end)
863+
return 0;
864+
865+
for (; buf_start < buf_end; buf_start++)
866+
sum += buf_start[0];
867+
868+
return 0xffffffff - sum;
869+
}
870+
871+
int amdgpu_virt_init_critical_region(struct amdgpu_device *adev)
872+
{
873+
struct amd_sriov_msg_init_data_header *init_data_hdr = NULL;
874+
uint32_t init_hdr_offset = adev->virt.init_data_header.offset;
875+
uint32_t init_hdr_size = adev->virt.init_data_header.size_kb << 10;
876+
uint64_t vram_size;
877+
int r = 0;
878+
uint8_t checksum = 0;
879+
880+
/* Skip below init if critical region version != v2 */
881+
if (adev->virt.req_init_data_ver != GPU_CRIT_REGION_V2)
882+
return 0;
883+
884+
if (init_hdr_offset < 0) {
885+
dev_err(adev->dev, "Invalid init header offset\n");
886+
return -EINVAL;
887+
}
888+
889+
vram_size = RREG32(mmRCC_CONFIG_MEMSIZE);
890+
if (!vram_size || vram_size == U32_MAX)
891+
return -EINVAL;
892+
vram_size <<= 20;
893+
894+
if ((init_hdr_offset + init_hdr_size) > vram_size) {
895+
dev_err(adev->dev, "init_data_header exceeds VRAM size, exiting\n");
896+
return -EINVAL;
897+
}
898+
899+
/* Allocate for init_data_hdr */
900+
init_data_hdr = kzalloc(sizeof(struct amd_sriov_msg_init_data_header), GFP_KERNEL);
901+
if (!init_data_hdr)
902+
return -ENOMEM;
903+
904+
amdgpu_device_vram_access(adev, (uint64_t)init_hdr_offset, (uint32_t *)init_data_hdr,
905+
sizeof(struct amd_sriov_msg_init_data_header), false);
906+
907+
/* Table validation */
908+
if (strncmp(init_data_hdr->signature,
909+
AMDGPU_SRIOV_CRIT_DATA_SIGNATURE,
910+
AMDGPU_SRIOV_CRIT_DATA_SIG_LEN) != 0) {
911+
dev_err(adev->dev, "Invalid init data signature: %.4s\n",
912+
init_data_hdr->signature);
913+
r = -EINVAL;
914+
goto out;
915+
}
916+
917+
checksum = amdgpu_virt_crit_region_calc_checksum(
918+
(uint8_t *)&init_data_hdr->initdata_offset,
919+
(uint8_t *)init_data_hdr +
920+
sizeof(struct amd_sriov_msg_init_data_header));
921+
if (checksum != init_data_hdr->checksum) {
922+
dev_err(adev->dev, "Found unmatching checksum from calculation 0x%x and init_data 0x%x\n",
923+
checksum, init_data_hdr->checksum);
924+
r = -EINVAL;
925+
goto out;
926+
}
927+
928+
memset(&adev->virt.crit_regn, 0, sizeof(adev->virt.crit_regn));
929+
memset(adev->virt.crit_regn_tbl, 0, sizeof(adev->virt.crit_regn_tbl));
930+
931+
adev->virt.crit_regn.offset = init_data_hdr->initdata_offset;
932+
adev->virt.crit_regn.size_kb = init_data_hdr->initdata_size_in_kb;
933+
934+
/* Validation and initialization for each table entry */
935+
if (IS_SRIOV_CRIT_REGN_ENTRY_VALID(init_data_hdr, AMD_SRIOV_MSG_IPD_TABLE_ID)) {
936+
if (!init_data_hdr->ip_discovery_size_in_kb ||
937+
init_data_hdr->ip_discovery_size_in_kb > DISCOVERY_TMR_SIZE) {
938+
dev_err(adev->dev, "Invalid %s size: 0x%x\n",
939+
amdgpu_virt_dynamic_crit_table_name[AMD_SRIOV_MSG_IPD_TABLE_ID],
940+
init_data_hdr->ip_discovery_size_in_kb);
941+
r = -EINVAL;
942+
goto out;
943+
}
944+
945+
adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_IPD_TABLE_ID].offset =
946+
init_data_hdr->ip_discovery_offset;
947+
adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_IPD_TABLE_ID].size_kb =
948+
init_data_hdr->ip_discovery_size_in_kb;
949+
}
950+
951+
if (IS_SRIOV_CRIT_REGN_ENTRY_VALID(init_data_hdr, AMD_SRIOV_MSG_VBIOS_IMG_TABLE_ID)) {
952+
if (!init_data_hdr->vbios_img_size_in_kb) {
953+
dev_err(adev->dev, "Invalid %s size: 0x%x\n",
954+
amdgpu_virt_dynamic_crit_table_name[AMD_SRIOV_MSG_VBIOS_IMG_TABLE_ID],
955+
init_data_hdr->vbios_img_size_in_kb);
956+
r = -EINVAL;
957+
goto out;
958+
}
959+
960+
adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_VBIOS_IMG_TABLE_ID].offset =
961+
init_data_hdr->vbios_img_offset;
962+
adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_VBIOS_IMG_TABLE_ID].size_kb =
963+
init_data_hdr->vbios_img_size_in_kb;
964+
}
965+
966+
if (IS_SRIOV_CRIT_REGN_ENTRY_VALID(init_data_hdr, AMD_SRIOV_MSG_RAS_TELEMETRY_TABLE_ID)) {
967+
if (!init_data_hdr->ras_tele_info_size_in_kb) {
968+
dev_err(adev->dev, "Invalid %s size: 0x%x\n",
969+
amdgpu_virt_dynamic_crit_table_name[AMD_SRIOV_MSG_RAS_TELEMETRY_TABLE_ID],
970+
init_data_hdr->ras_tele_info_size_in_kb);
971+
r = -EINVAL;
972+
goto out;
973+
}
974+
975+
adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_RAS_TELEMETRY_TABLE_ID].offset =
976+
init_data_hdr->ras_tele_info_offset;
977+
adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_RAS_TELEMETRY_TABLE_ID].size_kb =
978+
init_data_hdr->ras_tele_info_size_in_kb;
979+
}
980+
981+
if (IS_SRIOV_CRIT_REGN_ENTRY_VALID(init_data_hdr, AMD_SRIOV_MSG_DATAEXCHANGE_TABLE_ID)) {
982+
if (!init_data_hdr->dataexchange_size_in_kb) {
983+
dev_err(adev->dev, "Invalid %s size: 0x%x\n",
984+
amdgpu_virt_dynamic_crit_table_name[AMD_SRIOV_MSG_DATAEXCHANGE_TABLE_ID],
985+
init_data_hdr->dataexchange_size_in_kb);
986+
r = -EINVAL;
987+
goto out;
988+
}
989+
990+
adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_DATAEXCHANGE_TABLE_ID].offset =
991+
init_data_hdr->dataexchange_offset;
992+
adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_DATAEXCHANGE_TABLE_ID].size_kb =
993+
init_data_hdr->dataexchange_size_in_kb;
994+
}
995+
996+
if (IS_SRIOV_CRIT_REGN_ENTRY_VALID(init_data_hdr, AMD_SRIOV_MSG_BAD_PAGE_INFO_TABLE_ID)) {
997+
if (!init_data_hdr->bad_page_size_in_kb) {
998+
dev_err(adev->dev, "Invalid %s size: 0x%x\n",
999+
amdgpu_virt_dynamic_crit_table_name[AMD_SRIOV_MSG_BAD_PAGE_INFO_TABLE_ID],
1000+
init_data_hdr->bad_page_size_in_kb);
1001+
r = -EINVAL;
1002+
goto out;
1003+
}
1004+
1005+
adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_BAD_PAGE_INFO_TABLE_ID].offset =
1006+
init_data_hdr->bad_page_info_offset;
1007+
adev->virt.crit_regn_tbl[AMD_SRIOV_MSG_BAD_PAGE_INFO_TABLE_ID].size_kb =
1008+
init_data_hdr->bad_page_size_in_kb;
1009+
}
1010+
1011+
adev->virt.is_dynamic_crit_regn_enabled = true;
1012+
1013+
out:
1014+
kfree(init_data_hdr);
1015+
init_data_hdr = NULL;
1016+
1017+
return r;
1018+
}
1019+
8461020
void amdgpu_virt_init(struct amdgpu_device *adev)
8471021
{
8481022
bool is_sriov = false;

drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@
5454

5555
#define AMDGPU_VF2PF_UPDATE_MAX_RETRY_LIMIT 2
5656

57+
/* Signature used to validate the SR-IOV dynamic critical region init data header ("INDA") */
58+
#define AMDGPU_SRIOV_CRIT_DATA_SIGNATURE "INDA"
59+
#define AMDGPU_SRIOV_CRIT_DATA_SIG_LEN 4
60+
61+
#define IS_SRIOV_CRIT_REGN_ENTRY_VALID(hdr, id) ((hdr)->valid_tables & (1 << (id)))
62+
5763
enum amdgpu_sriov_vf_mode {
5864
SRIOV_VF_MODE_BARE_METAL = 0,
5965
SRIOV_VF_MODE_ONE_VF,
@@ -296,6 +302,9 @@ struct amdgpu_virt {
296302

297303
/* dynamic(v2) critical regions */
298304
struct amdgpu_virt_region init_data_header;
305+
struct amdgpu_virt_region crit_regn;
306+
struct amdgpu_virt_region crit_regn_tbl[AMD_SRIOV_MSG_MAX_TABLE_ID];
307+
bool is_dynamic_crit_regn_enabled;
299308

300309
/* vf2pf message */
301310
struct delayed_work vf2pf_work;
@@ -432,6 +441,8 @@ void amdgpu_virt_exchange_data(struct amdgpu_device *adev);
432441
void amdgpu_virt_fini_data_exchange(struct amdgpu_device *adev);
433442
void amdgpu_virt_init(struct amdgpu_device *adev);
434443

444+
int amdgpu_virt_init_critical_region(struct amdgpu_device *adev);
445+
435446
bool amdgpu_virt_can_access_debugfs(struct amdgpu_device *adev);
436447
int amdgpu_virt_enable_access_debugfs(struct amdgpu_device *adev);
437448
void amdgpu_virt_disable_access_debugfs(struct amdgpu_device *adev);

drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,37 @@ enum amd_sriov_crit_region_version {
7171
GPU_CRIT_REGION_V2 = 2,
7272
};
7373

74+
/* v2 layout offset enum (in order of allocation) */
75+
enum amd_sriov_msg_table_id_enum {
76+
AMD_SRIOV_MSG_IPD_TABLE_ID = 0,
77+
AMD_SRIOV_MSG_VBIOS_IMG_TABLE_ID,
78+
AMD_SRIOV_MSG_RAS_TELEMETRY_TABLE_ID,
79+
AMD_SRIOV_MSG_DATAEXCHANGE_TABLE_ID,
80+
AMD_SRIOV_MSG_BAD_PAGE_INFO_TABLE_ID,
81+
AMD_SRIOV_MSG_INITD_H_TABLE_ID,
82+
AMD_SRIOV_MSG_MAX_TABLE_ID,
83+
};
84+
85+
struct amd_sriov_msg_init_data_header {
86+
char signature[4]; /* "INDA" */
87+
uint32_t version;
88+
uint32_t checksum;
89+
uint32_t initdata_offset; /* 0 */
90+
uint32_t initdata_size_in_kb; /* 5MB */
91+
uint32_t valid_tables;
92+
uint32_t vbios_img_offset;
93+
uint32_t vbios_img_size_in_kb;
94+
uint32_t dataexchange_offset;
95+
uint32_t dataexchange_size_in_kb;
96+
uint32_t ras_tele_info_offset;
97+
uint32_t ras_tele_info_size_in_kb;
98+
uint32_t ip_discovery_offset;
99+
uint32_t ip_discovery_size_in_kb;
100+
uint32_t bad_page_info_offset;
101+
uint32_t bad_page_size_in_kb;
102+
uint32_t reserved[8];
103+
};
104+
74105
/*
75106
* PF2VF history log:
76107
* v1 defined in amdgim

0 commit comments

Comments
 (0)